迭代未扩展文件掩码的 $list

Iterate over a $list of unexpanded filemasks

我有一个 bash 脚本,它在软件发布期间 运行,用于验证所有源文件是否包含版权和许可 header。时不时地,我必须给它添加一个新的文件扩展名,因此我的 'find' 命令变得有点笨拙。我决定对其进行一些重构,以便更轻松地添加新文件类型。我想通过定义一个包含文件掩码列表的变量 FILEMASKS 来做到这一点。从概念上讲,它看起来像这样:

FILEMASKS="*.?pp *.[ch] *.sh"
echo FILEMASKS is \'$FILEMASKS\'

for _fs in $FILEMASKS; do
  echo \# find . -iname \'$_fs\'  # debug
          find . -iname \'$_fs\'  # (not really indented this way)
done

以上代码的输出不是我所期望的:

FILEMASKS is '*.?pp *.[ch] *.sh'
# find . -iname '*.?pp'
# find . -iname '*.[ch]'
# find . -iname 'check-license.sh'

基本上有两个问题:

  1. 只有 echo 行生成任何输出; find 的实际调用是无声的,表明没有找到匹配的内容。这令人费解,因为回显版本表明 find 命令的构造完全符合我的预期。 (如果我 copy-paste 回显输出到 shell,它会 return 一个文件列表。)
  2. for 循环扩展 $_fs 的值,在当前目录中有文件匹配 $_fs 的情况下(例如 'check-license.sh',对于 '* .sh') 然而,我想要的结果是让 $FILEMASKS 中的所有文件掩码进入我的 find 命令未展开。

[更新] 我刚刚找到了解决上面 #2 的方法:我从 FILEMASKS 中每个条目的开头删除了 *.变量,然后在 find 命令中 原位 添加它。所以,只剩下#1。但我仍然有兴趣看到 #2 的其他解决方案。

您可以使用数组作为掩码列表来规避这些问题。

像这样:

#! /bin/bash
exts=('*.txt' '*.jpg')

for ext in "${exts[@]}" ; do
  echo "* For mask [$ext]:"
  find . -iname "$ext"
done

我得到了这个输出(顶层目录包含一个 txt 和一个 jpg 文件,以确保没有发生早期的 globbing):

* For mask [*.txt]:
./b.txt
./bar/a.txt
* For mask [*.jpg]:
./foo/a.jpg
./b.jpg

您的问题 #1 是这样的:

$ find . -iname '*.txt'
./a.txt
$ find . -iname \'*.txt\'
$ touch "'b.txt'"
$ find . -iname \'*.txt\'
./'b.txt'

您要求 find 列出字面上与 '*.?pp' 匹配且文件名中包含单引号的文件。 (并且由于 * 和其他通配字符未被引用,因此在将参数传递给 find 之前,您将通过 shell 通配。)