Interaktywne usuwanie plików z listy

13

Chciałbym usunąć listę plików i zostać poproszony o potwierdzenie. Lista znajduje się w list.txtpliku. Dlaczego poniższe polecenie nie działa poprawnie?

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

Poprzednie polecenie nie czeka na mnie, ale na szczęście żaden plik nie jest usuwany.

Używam Bash.

Francesco Turco
źródło

Odpowiedzi:

20

rm -iodczytuje odpowiedź ze standardowego wejścia, które dziedziczy z whilepętli. Więc wiersz tekstu z list.txtjest używany jako odpowiedź na „naprawdę usunąć?” pytanie. Aby to naprawić, musisz oddzielić dwa źródła danych wejściowych. Najłatwiej jest readpobrać dane z oddzielnego deskryptora pliku:

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

Nie przekierowujesz już standardowego wejścia (fd 0) dla pętli while, więc rmbędziesz czytać z terminala zgodnie z potrzebami.

Możesz też zrobić:

IFS=$'\n' # set field separator to newline
set -f    # disable globbing upon command substitution
rm -i -- $(cat list.txt)

Lub z GNU xargs:

xargs -rd '\n' --arg-file=list.txt rm -i --
chepner
źródło
1
Więc jeśli miałbym na liście plik o nazwie y, poprzedni plik zostałby usunięty?
Francesco Turco
5
Nie tylko y, ale każde imię zaczynające się od y. Najwyraźniej rmpo prostu patrzy na pierwszy znak jakiejkolwiek odpowiedzi, jaką otrzymuje: „y” jest tak, wszystko inne nie.
chepner
2

Aby uzyskać coś bardziej wymyślnego niż odpowiadanie na tak lub nie na każdy plik, można użyć iselectinteraktywnego wyboru opartego na ncurses. na przykład

iselect -a -m < list.txt | xargs -d '\n' -r echo rm 

lub aby umożliwić wybór plików w bieżącym katalogu:

find . -maxdepth 1 -type f | iselect -a -m | xargs -d '\n' -r echo rm

Spowoduje to wyświetlenie pełnoekranowego (pełnego terminala) wykazu opartego na ncurses, gdzie pliki można wybierać i usuwać do woli, naciskając SPACJĘ. naciśnij ENTER, aby zaakceptować wybrane opcje (wybrane wpisy zostaną wydrukowane na standardowym wyjściu) lub qwyjść z menu (nic nie zostanie wydrukowane na standardowym wyjściu). naciśnij hpo pomoc.

Uwaga echo rm- napisałem to tak do testów. zmień to na tylko wtedy, rmgdy masz pewność, że rozumiesz, co robi.

Zauważ też, że xargsjest tutaj używany \njako separator wejściowy. To nie zadziała, jeśli którakolwiek z nazw plików zawiera znaki końca linii. Z tego też powodu iselectnie będzie działać poprawnie - oczekuje jednego elementu w wierszu - niestety iselectnie ma opcji wejścia lub wyjścia zakończonego zerem .

iselectjest spakowany dla Debiana, prawdopodobnie Ubuntu i innych dystrybucji. strona główna znajduje się pod adresem http://www.ossp.org/pkg/tool/iselect/

cas
źródło