Các vỏ mở rộng *
chỉ khi un-trích dẫn, bất kỳ điểm dừng trích dẫn mở rộng bằng vỏ.
Ngoài ra, một mở rộng cú đúp cần phải được bỏ qua để được mở rộng bởi vỏ.
Công việc này (cho phép sử dụng echo để xem shell làm gì):
$ echo *.{ext1,ext2}
a.ext1 b.ext1 a.ext2 b.ext2
Ngay cả khi có các tệp có một số tên khác:
$ touch {a,b}.{ext1,ext2} {c,d}.{ext3,ext4} none
ls
a.ext1 a.ext2 b.ext1 b.ext2 c.ext3 c.ext4 d.ext3 d.ext4 none
$ echo *.{ext1,ext2}
a.ext1 b.ext1 a.ext2 b.ext2
Tại sao điều đó làm việc?
Điều quan trọng là chúng tôi hiểu lý do tại sao điều đó làm việc. Đó là vì thứ tự mở rộng. Đầu tiên là "Mở rộng cú đúp" và sau đó (lần cuối cùng) "Mở rộng tên đường" (hay còn gọi là mở rộng toàn cầu).
Brace --> Parameter (variable) --> Pathname
Chúng tôi có thể tắt "Mở rộng tên đường dẫn" trong giây lát:
$ set -f
$ echo *.{ext1,ext2}
*.ext1 *.ext2
"Mở rộng tên đường dẫn" nhận được hai đối số: *.ext1
và *.ext2
.
$ set +f
$ echo *.{ext1,ext2}
a.ext1 b.ext1 a.ext2 b.ext2
Vấn đề là chúng ta không thể sử dụng một biến để mở rộng niềng răng.
Nó đã được giải thích nhiều lần trước khi sử dụng một biến trong "Mở rộng cú đúp"
Để mở rộng "Mở rộng cú đúp" là kết quả của "Mở rộng biến", bạn cần gửi lại dòng lệnh cho trình bao với eval
.
$ list={ext1,ext2}
$ eval echo '*.'"$list"
Cú đúp -> Biến -> Glob | | -> Cú đúp -> Biến -> Glob
........ được trích dẫn ở đây -> ^^ ^ ^ ^ ^ ^ ^ | eval ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^
Giá trị của tên tệp không mang lại vấn đề thực thi cho eval:
$ touch 'a;date;.ext1'
eval echo '*.'"$list"
a;date;.ext1 a.ext1 b.ext1 a.ext2 b.ext2
Nhưng giá trị của $list
có thể không an toàn. Tuy nhiên, giá trị của $list
được đặt bởi người viết kịch bản. Người viết kịch bản kiểm soát eval
: Chỉ không sử dụng các giá trị được đặt bên ngoài cho $list
. Thử cái này:
#!/bin/bash
touch {a,b,c}.ext{1,2}
list=ext{1,2}
eval ls -l -- '*.'"$list"
Một sự thay thế tốt hơn.
Một cách khác (không có eval) là sử dụng Bash "Các mẫu mở rộng" :
#!/bin/bash
shopt -s extglob
list='@(ext1|ext2)'
ls -- *.$list
Lưu ý: Xin lưu ý rằng cả hai giải pháp (eval và mẫu) (như được viết) đều an toàn cho tên tệp có dấu cách hoặc dòng mới. Nhưng sẽ thất bại cho a $list
với khoảng trắng, vì không $list
được trích dẫn hoặc eval xóa dấu ngoặc kép.
eval ls $secondList
hoạt động tốt ở đây ... bạn đang cố gắng đạt được điều gì?