Tương tác xóa các tập tin từ một danh sách


12

Tôi muốn xóa danh sách các tập tin và được yêu cầu xác nhận. Danh sách có trong list.txttập tin. Tại sao lệnh sau không hoạt động đúng?

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

Lệnh trước không đợi tôi nhưng may mắn là không có tệp nào bị xóa.

Tôi đang sử dụng Bash.

Câu trả lời:


19

rm -iđọc câu trả lời của nó từ đầu vào tiêu chuẩn, mà nó kế thừa từ whilevòng lặp. Vì vậy, một dòng văn bản từ list.txtđang được sử dụng làm câu trả lời cho "thực sự loại bỏ?" câu hỏi Để khắc phục, bạn sẽ cần tách hai nguồn đầu vào. Cách dễ nhất là readlấy đầu vào từ một bộ mô tả tệp riêng biệt:

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

Bạn không còn chuyển hướng đầu vào tiêu chuẩn (fd 0) cho vòng lặp while, vì vậy rmsẽ đọc từ thiết bị đầu cuối như mong muốn.

Ngoài ra, bạn có thể đã thực hiện:

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

Hoặc, với GNU xargs:

xargs -rd '\n' --arg-file=list.txt rm -i --

1
Vì vậy, nếu tôi có trong danh sách một tập tin có tên y, tập tin trước đó sẽ bị xóa?
Francesco Turco

5
Không chỉ y, nhưng bất kỳ tên bắt đầu với y. Rõ ràng, rmchỉ cần nhìn vào nhân vật đầu tiên của bất kỳ phản hồi nào mà nó nhận được: 'y' là có, bất cứ điều gì khác là không.
chepner

1

Đối với một cái gì đó lạ hơn một chút so với trả lời có hoặc không cho mỗi tệp, bạn có thể sử dụng iselectcho lựa chọn dựa trên ncurses tương tác. ví dụ

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

hoặc để cho phép lựa chọn các tập tin trong thư mục hiện tại:

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

Điều đó sẽ hiển thị danh sách dựa trên toàn màn hình (toàn bộ thiết bị đầu cuối), trong đó các tệp có thể được chọn và bỏ chọn theo ý muốn bằng cách nhấn SPACE. nhấn ENTER để chấp nhận các lựa chọn của bạn (các mục được chọn sẽ được in trên thiết bị xuất chuẩn) hoặc qđể thoát (không có gì được in ra thiết bị xuất chuẩn). nhấn hđể được giúp đỡ

Lưu ý rằng echo rm- tôi đã viết nó như thế để thử nghiệm. thay đổi nó thành chỉ rmkhi bạn tự tin bạn hiểu những gì nó đang làm.

Cũng lưu ý rằng xargsđang được sử dụng ở đây với \nvai trò là dấu phân tách đầu vào. Điều này sẽ không hoạt động nếu bất kỳ tên tệp nào có các ký tự dòng trong đó. Đối với vấn đề đó, iselectsẽ không hoạt động chính xác - nó mong đợi một mục trên mỗi dòng - iselectthật không may, không có tùy chọn cho đầu vào hoặc đầu ra kết thúc null.

iselectđược đóng gói cho debian, có thể là Ubuntu và các bản phát hành khác. trang chủ có tại http://www.ossp.org/pkg/tool/iselect/

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.