从列表中交互式删除文件


13

我想删除文件列表并要求确认。列表在list.txt文件中。为什么以下命令无法正常工作?

while read i; do rm -i $i; done < list.txt

前面的命令不会等我,但是幸运的是没有文件被删除。

我正在使用Bash。

Answers:


20

rm -iwhile循环继承的标准输入中读取答案。因此,来自的一行文字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 --

1
因此,如果列表中有一个名为的文件y,那么先前的文件会被删除吗?
Francesco Turco

5
不只是y,而是任何以y。开头的名字。显然,rm只要看一下收到的任何响应的第一个字符:“ y”是是,其他什么都不是。
chepner 2012年

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的全屏(全终端)列表,在其中可以通过按SPACE随意选择和取消选择文件。按ENTER接受您的选择(所选条目将打印在stdout上),或q退出(不打印任何内容到stdout)。按h求助。

请注意echo rm-我已经将其编写为用于测试。只要rm确信您了解它在做什么,就将其更改为。

另请注意,xargs此处\n用作输入分隔符。如果任何文件名中包含换行符,则此功能将无效。因此,它们iselect也将无法正常工作-希望每行有一个项目-不幸的是,iselect没有以空值结尾的输入或输出的选项。

iselect是为debian,也许ubuntu和其他发行版打包的。主页位于http://www.ossp.org/pkg/tool/iselect/

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.