2012-09-07 32 views
6

xem xét vòng lặp đơn giản này:Simple Bash - cho f trong *

for f in *.{text,txt}; do echo $f; done 

Tôi muốn vang tên tập tin chỉ có giá trị. Sử dụng biến $ f trong một tập lệnh, mọi thứ hoạt động tốt trừ khi không có bất kỳ tệp nào của tiện ích mở rộng đó. Trong trường hợp một tập hợp trống, $ f được đặt thành * .text và dòng trên là echos:

*.text 
*.txt 

thay vì không lặp lại gì cả. Điều này tạo ra một lỗi nếu bạn đang cố gắng sử dụng $ f cho bất cứ điều gì đó là mong đợi một tên tập tin thực tế thực tế và thay vào đó được *.

Nếu có bất kỳ tệp nào khớp với ký tự đại diện để nó không phải là bộ trống, mọi thứ hoạt động như tôi muốn. ví dụ.

123.text 
456.txt 
789.txt 

Làm cách nào để làm điều này mà không có lỗi và không có sự phức tạp quá mức của chuỗi đầu tiên phù hợp với $ f cho dấu hoa thị?

Trả lời

13

Đặt tùy chọn nullglob ion.

$ for f in *.foo ; do echo "$f" ; done 
*.foo 
$ shopt -s nullglob 
$ for f in *.foo ; do echo "$f" ; done 
$ 
+0

Đây chính xác là những gì tôi đang tìm kiếm. Cảm ơn! – user1610022

3

Bạn có thể kiểm tra xem các tập tin thực sự tồn tại:

for f in *.{text,txt}; do if [ -f $f ]; then echo $f; fi; done 

hoặc bạn có thể sử dụng find lệnh:

for f in $(find -name '*.text' -o -name '*.txt'); do 
    echo $f 
done 
+0

Kiểm tra xem $ f có thực sự là một tệp hoạt động tốt hay không. Nhưng, nó là một thử nghiệm bổ sung mà tôi đã hy vọng tránh. – user1610022

0

Ngoài ra, nếu bạn có khả năng sử dụng bên ngoài của ls, bạn có thể thoát kết quả của nó bằng cách sử dụng

for f in `ls *.txt *.text`; 
+0

Nó không hoạt động nếu tên tập tin chứa không gian. – choroba

+0

Có thể sửa lỗi bằng cách đặt '$ IFS' chính xác. Ngược lại với tùy chọn nullglob, điều này có thể xảy ra khá an toàn bên trong một kịch bản lệnh shell mà không cần gọi đến shopt. – ThePadawan

+0

Vui lòng cho biết cách thực hiện. Ngoài ra, 'shopt' là một nội trang dựng sẵn, vì vậy bạn không gọi nó là" out ". – choroba