Có bất kỳ lợi thế nào trong việc chỉ định './' trong vòng lặp for bằng cách sử dụng toàn cầu không?


10

Tôi có ấn tượng rằng nó có thể an toàn hơn để sử dụng ./*.fastqkhi tìm kiếm các tập tin kết thúc bằng .fastq. Ví dụ, ./sẽ ngăn chặn việc chụp tệp .fastq. Điều này rõ ràng là sai, như trong ví dụ dưới đây:

TMP_DIR=$(mktemp --directory)
mkdir -p ${TMP_DIR}
(cd ${TMP_DIR}
 touch {a,b,c,}.fastq
 ls -a
 echo ""

 echo "# match all:"
 for f in *.fastq ; do
     echo "${f}"
 done
 echo ""

 echo "# with ./:"
 for f in ./*.fastq ; do
     echo "${f}"
 done
)
rm -rf ${TMP_DIR}
.
..
a.fastq
b.fastq
c.fastq
.fastq

# match all:
a.fastq
b.fastq
c.fastq

# with ./:
./a.fastq
./b.fastq
./c.fastq

Không *.fastqphải cũng không ./*.fastqphù hợp với các tập tin .fastq. Vì vậy, tôi tự hỏi bây giờ, có bất kỳ điểm sử dụng ./*.fastqở đây, hoặc ./*nói chung?


1
Điểm thông thường ./*là nó đảm bảo rằng các tên bắt đầu -không được coi là tùy chọn.
Charles Duffy

Câu trả lời:


15

Đó là hành vi ký tự đại diện đáng ngạc nhiên ban đầu, vì mô tả cho *ký tự đại diện nói:

Phù hợp với bất kỳ chuỗi, bao gồm cả chuỗi null.

... Cho đến khi bạn nhận ra khoảng thời gian đó hơi đặc biệt khi đó là ký tự đầu tiên của tên tệp. Các văn bản giới thiệu 3.5.8 Filename Expansionnói rằng:

Khi một mẫu được sử dụng để mở rộng tên tệp, ký tự '.' ở đầu tên tệp hoặc ngay sau dấu gạch chéo phải được khớp rõ ràng, trừ khi tùy chọn shell dotglob được đặt.

"Mẫu sử dụng" của các ký tự đại diện tiền tố ./rất hữu ích cho Xử lý các tên có dấu gạch đầu dòng trong bash shell , như Steeldo nhận xét. Nó không có tác dụng đối với việc mở rộng ký tự đại diện / tên tệp, nhưng giúp xử lý tên tệp an toàn hơn / dễ dàng hơn khi bạn tham chiếu đến chúng, nếu chúng bắt đầu bằng các ký tự mà các chương trình đó có thể hiểu sai là các tùy chọn. Ví dụ:

# I want a file named `-n`
$ touch -n
touch: invalid option -- 'n'
Try 'touch --help' for more information.
$ touch -- -n
### ok
$ touch ./-n
### ok

... và bây giờ tôi một tệp có tên -n, nếu tôi tình cờ lặp lại nó bằng ký tự đại diện:

for file in *n
do
  echo "$file"
done

... Tôi không nhận được đầu ra!

Nhưng nếu tôi đặt tiền tố ký tự đại diện với ./,

for file in ./*n
do
  echo "$file"
done
./-n

... Tôi thấy tên tệp.

Đây là một ví dụ đơn giản cho mục đích trình diễn; xem thêm Tại sao printf tốt hơn echo? vì lý do này và những người khác. Các tiện ích khác sẽ được tăng gấp ba bởi các tùy chọn khác, vì vậy tốt hơn là trình bày tên tệp cho các tiện ích một cách an toàn nhất có thể. Nếu bạn không đặt tiền tố ký tự đại diện để "thoát" tên tệp, bạn phải "bảo vệ" các tiện ích của mình theo những cách khác; một phổ biến là báo hiệu kết thúc các tùy chọn với --, ví dụ:

for file in *n
do
  mv -- "$file" backup/"$file"
done

... sẽ chuyển -ntên tệp một cách an toàn đến mv(như được thấy dưới đây set -x):

mv -- -n backup/-n
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.