Tar*_*lpe 9 command-line bash scripts
我有一些带有\n字符名称的文件夹。
例如:
$ ls
''$'\n''Test'
Run Code Online (Sandbox Code Playgroud)
那是指一个带有测试名称的文件夹,名称前有一个空行。
因此,当我在其父目录中运行一些这样的脚本时:
while IFS= read -r d; do
rmdir $d
done < <(find * -type d)
Run Code Online (Sandbox Code Playgroud)
表明:
rmdir: failed to remove '': No such file or directory
rmdir: failed to remove 'Test': No such file or directory
Run Code Online (Sandbox Code Playgroud)
因为它运行了两次,一次 on\n和另一个 on Test,因为文件夹名称有两行。
那么我该如何解决这个问题,让脚本知道\nTest只有一个文件夹?
Ser*_*nyy 12
您在那里只有一个命令,因此find使用-exec标志调用进行调用就足够了rmdir:
find -depth -type d -exec rmdir {} \;
Run Code Online (Sandbox Code Playgroud)
或者使用 中的-delete选项 find -type d -delete,但它不适用于非空目录。为此,您还需要-empty标志。还要注意,-delete意味着-depth可以跳过。因此,另一种可行的替代方法是将所有内容都作为一个过程:
find -type d -empty -delete
Run Code Online (Sandbox Code Playgroud)
如果目录不为空,请使用rm -rf {} \;. 要仅隔离具有\nin 文件名的目录,我们可以将 bash 的ANSI-C 引用 $'...'与-name选项结合起来:
find -type d -name $'*\n*' -empty -delete
Run Code Online (Sandbox Code Playgroud)
POSIX-ly,我们可以这样处理:
find -depth -type d -name "$(printf '*\n*' )" -exec rmdir {} \;
Run Code Online (Sandbox Code Playgroud)
值得一提的是,如果您的目标是删除目录,那么-delete就足够了,但是如果您想在目录上执行命令,则-exec最合适。
也可以看看
Byt*_*der 10
您可以使用 shell globs 而不是find:
for d in */ ; do
rmdir "$d"
done
Run Code Online (Sandbox Code Playgroud)
shell glob*/匹配当前目录中的所有文件夹。这个 for 循环结构会自动处理正确的分词。
请注意,根据您的 shell 选项,这可能会忽略隐藏文件夹(名称以 . 开头)。可以使用命令更改该行为以匹配当前会话的所有文件shopt -s dotglob。
也不要忘记总是引用你的变量。
到目前为止编写的两个答案rmdir每个目录调用一次,但是rmdir我想知道可以使用多个参数:没有更有效的方法吗?
一个可以简单地做
rmdir */
Run Code Online (Sandbox Code Playgroud)
这绝对是最简单和最有效的方法,但在许多目录的情况下可能会引发错误(请参阅gnome-terminal 中命令行参数的最大长度是多少?)。如果您希望这种方法以递归方式工作,请启用globstarshell 选项shopt -s globstar并使用**/*/代替*/。
使用 GNU find(如果我们不只是想使用-delete),我们可以做
find -depth -type d -exec rmdir {} +
Run Code Online (Sandbox Code Playgroud)
它构建命令行的方式“与xargs构建其命令行的方式大致相同”(man find)。替代-depth的-maxdepth 1,如果你不希望它递归工作。
steeldriver 在这个答案中解释了第三种和 IMO 的绝妙方法:
printf '%s\0' */ | xargs -0 rmdir
Run Code Online (Sandbox Code Playgroud)
这使用内置的 shellprintf来构建一个以零分隔的参数列表,然后将该列表通过管道传输到xargs该列表,rmdir根据需要的频率进行调用。你可以让它递归地工作,shopt -s globstar而**/*/不是*/像上面那样。