我想删除文件列表并要求我确认。该列表位于list.txt
文件中。为什么下面的命令不能正常工作?
while read i; do rm -i $i; done < list.txt
前面的命令不会等待我,但幸运的是没有文件被删除。
我正在使用 Bash。
答案1
rm -i
从标准输入读取答案,该答案是从while
循环继承的。因此,来自的一行文本list.txt
被用作“真的删除吗?”的答案。问题。要解决此问题,您需要将两个输入源分开。最简单的方法是read
从单独的文件描述符获取输入:
while IFS= read <&3 -r i; do
rm -i -- "$i" # Quote the file name, not just to be safe,
# but because it's the right syntax.
done 3< list.txt
您不再为 while 循环重定向标准输入 (fd 0),因此rm
将根据需要从终端读取。
或者,你也可以这样做:
IFS=$'\n' # set field separator to newline
set -f # disable globbing upon command substitution
rm -i -- $(cat list.txt)
或者,使用 GNU xargs:
xargs -rd '\n' --arg-file=list.txt rm -i --
答案2
对于比对每个文件回答是或否更奇特的事情,您可以使用iselect
基于 ncurses 的交互式选择。例如
iselect -a -m < list.txt | xargs -d '\n' -r echo rm
或允许选择当前目录中的文件:
find . -maxdepth 1 -type f | iselect -a -m | xargs -d '\n' -r echo rm
这将显示一个全屏(全终端)基于 ncurses 的列表,其中可以通过按空格键随意选择和取消选择文件。按 ENTER 接受您的选择(所选条目将打印在标准输出上),或q
退出(不打印任何内容到标准输出上)。按h
寻求帮助。
请注意echo rm
- 我已经这样编写以进行测试。rm
一旦您确信自己了解了它在做什么,就将其更改为。
另请注意,xargs
此处使用 with\n
作为输入分隔符。如果任何文件名中包含换行符,则此操作将不起作用。就此而言,它iselect
也无法正常工作 - 它需要每行一个项目 - 不幸的是,iselect
没有空终止输入或输出的选项。
iselect
是为 debian 打包的,可能还有 ubuntu 和其他发行版。主页位于http://www.ossp.org/pkg/tool/iselect/