Menghapus file secara interaktif dari daftar

12

Saya ingin menghapus daftar file dan dimintai konfirmasi. Daftarnya ada dalam list.txtfile. Mengapa perintah berikut ini tidak berfungsi dengan baik?

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

Perintah sebelumnya tidak menunggu saya tetapi untungnya tidak ada file yang dihapus.

Saya menggunakan Bash.

Francesco Turco
sumber

Jawaban:

19

rm -imembaca jawabannya dari input standar, yang diwarisi dari whileloop. Jadi sebaris teks dari list.txtdigunakan sebagai jawaban untuk "benar-benar menghapus?" pertanyaan. Untuk memperbaikinya, Anda harus memisahkan kedua sumber input. Cara termudah adalah dengan readmengambil input dari deskriptor file terpisah:

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

Anda tidak lagi mengarahkan input standar (fd 0) untuk loop sementara, sehingga rmakan membaca dari terminal seperti yang diinginkan.

Atau, Anda bisa melakukannya:

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

Atau, dengan GNU xargs:

xargs -rd '\n' --arg-file=list.txt rm -i --
chepner
sumber
1
Jadi jika saya memiliki dalam daftar file bernama y, file sebelumnya akan dihapus?
Francesco Turco
5
Bukan hanya y, tetapi nama apa pun yang dimulai dengan y. Tampaknya, lihat rmsaja karakter pertama dari respons apa pun yang diterimanya: 'y' adalah ya, yang lain tidak.
chepner
1

Untuk sesuatu yang sedikit lebih menarik daripada menjawab ya atau tidak untuk setiap file, Anda dapat menggunakan iselectpilihan berbasis ncurses interaktif. misalnya

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

atau untuk mengizinkan pemilihan file dalam direktori saat ini:

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

Itu akan menampilkan daftar ncurses berbasis layar penuh (terminal penuh), di mana file dapat dipilih dan tidak dipilih sesuka hati dengan menekan SPACE. tekan ENTER untuk menerima pilihan Anda (entri yang dipilih akan dicetak pada stdout), atau quntuk berhenti (tidak ada yang dicetak untuk stdout). tekan huntuk bantuan.

Perhatikan echo rm- saya sudah menulisnya seperti itu untuk pengujian. ubah menjadi hanya rmsekali Anda yakin Anda mengerti apa yang dilakukannya.

Perhatikan juga bahwa xargssedang digunakan di sini dengan \nsebagai pemisah input. Ini tidak akan berfungsi jika ada nama file yang memiliki karakter linefeed di dalamnya. Dalam hal ini, iselecttidak akan berfungsi dengan baik - ia mengharapkan satu item per baris - sayangnya, iselecttidak memiliki opsi untuk input atau output yang diakhiri null.

iselectDikemas untuk debian, mungkin ubuntu dan distro lainnya juga. beranda ada di http://www.ossp.org/pkg/tool/iselect/

cas
sumber