使用 glob 在 for 循环中指定 './' 有什么好处吗?

Fré*_*ahé 10 shell bash wildcards

我的印象是./*.fastq在搜索以.fastq. 例如,./会阻止捕获文件.fastq。这显然是错误的,如下例所示:

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}
Run Code Online (Sandbox Code Playgroud)
.
..
a.fastq
b.fastq
c.fastq
.fastq

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

# with ./:
./a.fastq
./b.fastq
./c.fastq
Run Code Online (Sandbox Code Playgroud)

既不匹配*.fastq也不./*.fastq匹配文件.fastq。所以我现在想知道,在这里使用./*.fastq./*一般使用有什么意义吗?

Jef*_*ler 15

这最初是令人惊讶的通配符行为,因为*通配符的描述说:

匹配任何字符串,包括空字符串。

... 直到您意识到当它是文件名的第一个字符时,句点有点特殊。中的介绍性文字是这样3.5.8 Filename Expansion说的:

当模式用于文件名扩展时,字符 '.' 除非设置了 shell 选项 dotglob,否则在文件名的开头或紧跟在斜杠后面的必须显式匹配。

通配符前缀的“使用模式” ./正如 steeldriver 评论的那样,在 bash shell 中处理带有前导破折号的名称时很有。它对通配符/文件名扩展没有影响,但如果文件名以那些程序可能会误解为选项的字符开头,则可以更安全/更轻松地处理文件名。例如:

# I want a file named `-n`
$ touch -n
touch: invalid option -- 'n'
Try 'touch --help' for more information.
$ touch -- -n
### ok
$ touch ./-n
### ok
Run Code Online (Sandbox Code Playgroud)

......现在我 一个名为 的文件-n,如果我碰巧用通配符遍历它:

for file in *n
do
  echo "$file"
done
Run Code Online (Sandbox Code Playgroud)

...我没有输出!

但是如果我在通配符前面加上 ./,

for file in ./*n
do
  echo "$file"
done
./-n
Run Code Online (Sandbox Code Playgroud)

...我看到文件名。

这是一个用于演示目的的简单示例;另请参阅为什么 printf 比 echo 好?出于这个原因和其他原因。其他实用程序会被其他选项绊倒,因此最好尽可能安全地将文件名提供给实用程序。如果您没有将通配符作为“转义”文件名的前缀,则必须以其他方式“保护”您的实用程序;一种常见的方法是用 表示选项的结束--,例如:

for file in *n
do
  mv -- "$file" backup/"$file"
done
Run Code Online (Sandbox Code Playgroud)

...这将安全地将-n文件名传递给mv(如下所示set -x):

mv -- -n backup/-n
Run Code Online (Sandbox Code Playgroud)