Tránh các lỗi do dấu hoa thị chưa được mở rộng


16

Trong bash tôi thường sử dụng các vòng lặp for như sau

for file in *.type; do 
  sommecommand "$file"; 
done;

để thực hiện một thao tác cho tất cả các tệp phù hợp *.type. Nếu không có tệp có kết thúc này được tìm thấy trong các thư mục làm việc thì dấu hoa thị không được mở rộng và thông thường tôi sẽ nhận được thông báo lỗi nói rằng ai đó đã không tìm thấy tệp. Tôi có thể nghĩ ngay đến một số cách để tránh lỗi này. Nhưng thêm một điều kiện dường như không phải là rất thanh lịch. Có một cách ngắn gọn và sạch sẽ để đạt được điều này?

Câu trả lời:


20

Có, chạy lệnh sau:

shopt -s nullglob

nó sẽ vô hiệu hóa trận đấu và không có lỗi nào được kích hoạt.

  • nếu bạn muốn hành vi này theo mặc định, hãy thêm lệnh trong ~/.bashrc
  • nếu bạn muốn phát hiện một quả cầu null trong vỏ POSIX, hãy thử

    for i in *.txt; do
      [ "$i" = '*.txt' ] && [ ! -e '*.txt' ] && continue
    done

Xem http://mywiki.wooledge.org/NullGlob


1
Lưu ý rằng thực sự có thể có một tệp được gọi *.txt. Nó sẽ là giá trị kiểm tra nếu các tập tin tồn tại.
Chris Xuống

bài chỉnh sửa cho phù hợp.
Gilles Quenot

@ChrisDown Lưu ý rằng nhận xét tương tự như câu trả lời của bạn được áp dụng tại đây (với hậu quả nghiêm trọng hơn có thể xảy ra do breakthay vì continue).
Stéphane Chazelas

6

Trong bash, bạn có thể sử dụng shopt -s nullglobđể mở rộng thành một mảng trống nếu không có kết quả khớp.

Trong shell POSIX mà không có nullglob, bạn có thể tránh vấn đề này bằng cách kiểm tra xem tên tệp được truyền có thực sự tồn tại hay không bằng cách [ -e "$file" ] || [ -L "$file" ] || continuelà phần đầu tiên của forvòng lặp của bạn .


1
Lưu ý rằng nó sẽ không hoàn toàn tương đương vì [ -esẽ trả về false cho các tệp không thể truy cập hoặc các tệp là liên kết tượng trưng đến các tệp không thể truy cập hoặc không tồn tại.
Stéphane Chazelas

@StephaneChazelas, hãy để những điểm về symlink được thừa nhận. Nhưng bạn có ý nghĩ gì về "tập tin không thể truy cập"? Ngay cả khi tôi chmod 0 the_file, [ -e the_file ]vẫn đánh giá đúng, vì vậy nó phải là một cái gì đó khác.
dubiousjim

1
gửi chỉnh sửa để xử lý các liên kết tượng trưng bị hỏng. hy vọng đó là ok.
dubiousjim

2
@dubiousjim mkdir -p x/{a,b} && chmod 444 x && echo x/* && [ -e x/a ],. x / a không thể truy cập nhưng vì x có thể đọc được nên x / * sẽ mở rộng.
Stéphane Chazelas

@StephaneChazelas, thật tuyệt, cảm ơn vì đã giải thích.
dubiousjim

4

Kỹ thuật thông thường cho đạn pháo không có nullglobtùy chọn là

set -- [*].type *.type
case $1$2 in
  '[*].type*.type') shift 2;;
  *) shift
esac
for file do
  cmd  -- "$file"
done

Phần bổ sung [*].typelà để bao gồm trường hợp có một tệp được gọi *.typetrong thư mục hiện tại.

Bây giờ, nếu bạn muốn bao gồm các tệp chấm, điều đó trở nên phức tạp hơn .

Tôi tin rằng kỹ thuật này đã được Laura Fairhead đặt ra trên usenet vài năm trước.


0

find . -name '*.type' -maxdepth 0 -exec somecommand "{}" ";"

Điều này loại bỏ hoàn toàn forvòng lặp và vỏ của vỏ khỏi phương trình. findsẽ thực thi -execlệnh một lần cho mỗi trận đấu và nếu không có kết quả khớp, nó sẽ không bao giờ được thực thi. Các -maxdepth 0hướng dẫn tìm thấy không tái diễn thành các thư mục con của đối số đường dẫn được đặt tên ( ., trong trường hợp này).

Nhược điểm là nó liên quan đến một ứng dụng khác, mặc dù có một ứng dụng có mặt trên hầu hết mọi hệ thống Linux ngoài kia (và có lẽ hầu hết các Unix cũng vậy).

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.