Интерактивное удаление файлов из списка

12

Я хотел бы удалить список файлов и запросить подтверждение. Список находится в list.txtфайле. Почему следующая команда не работает должным образом?

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

Предыдущая команда не ждет меня, но, к счастью, ни один файл не удален.

Я использую Bash.

Франческо Турко
источник

Ответы:

19

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

Вы больше не перенаправляете стандартный ввод (fd 0) для цикла while, поэтому 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 --
chepner
источник
1
Итак, если бы у меня в списке был файл с именем y, предыдущий файл был бы удален?
Франческо Турко
5
Не просто y, а любое имя, начинающееся с y. По-видимому, rmпросто смотрит на первый символ полученного ответа: «у» - да, все остальное - нет.
Chepner
1

Для чего-то более изящного, чем ответ «да» или «нет» на каждый файл, вы можете использовать его 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что здесь используется \nв качестве разделителя ввода. Это не будет работать, если любое из имен файлов содержит символы перевода строки. В этом отношении, iselectон также не будет работать должным образом - он ожидает один элемент на строку - к сожалению, iselectне имеет опции для ввода или вывода с нулевым символом в конце.

iselectупакован для Debian, возможно Ubuntu и других дистрибутивов. домашняя страница находится по адресу http://www.ossp.org/pkg/tool/iselect/

саз
источник