如果我执行
find . -name \*\.txt | while read f; do /bin/rm -i "$f"; done
rm
问道:
/ bin / rm:使用spaces.txt删除常规空文件'./some文件名'?
但命令退出而不等待答案。为什么这样以及如何解决它?
关于此主题的另一个问题,https://unix.stackexchange.com/questions/398872/rm-ir-does-not-work-inside-a-loop循环遍历ls
输出,但在我的情况下STDIN
是find
的输出,包含多个文件,每个文件都有可能其中有空格,所以我无法切换到非循环方式。
答案 0 :(得分:3)
while IFS= read -r -d '' f <&3; do
rm -i -- "$f"
done 3< <(find . -name '*.txt' -print0)
read -i
用于输入的文件描述符不同的文件描述符上。在这里,我们在重定向上使用FD 3(3<
,仅在<&3
上使用read
。-r
传递给read
,或文件名中的文字反斜杠将由read
使用,而不是放在已填充的变量中。-print0
侧的find
和-d ''
侧的read
。答案 1 :(得分:2)
使用-print
的{{1}}操作,而不是循环find
find
行动所产生的内容:
-exec
在此命令中,find . -name \*\.txt -exec rm -i -- {} +
表示由{}
迭代的元素,而find
都会分隔+
执行的命令,并声明它应该替换find -exec
它可以同时使用尽可能多的元素(作为替代方案,您可以使用{}
为每个元素执行一次命令)。 \;
之后的--
确保rm -i
列出的文件不会被解释为find
选项,如果它们以短划线开头但正确作为文件名。
这不仅更简洁(虽然不容易理解),但它也避免了与天真解决方案所具有的特殊字符相关的问题。
答案 2 :(得分:-1)
因为rm
从循环继承了它的标准输入,循环连接到左侧的输出。因此,在read f
获得名称foo
之后,rm
无法从标准输入读取。这就是rm
自行退出的原因。
如果您需要rm -i
提示,请不要使用管道。有很多选择。其中之一是
rm -i $(echo foo)