循环访问$list未展开的文件掩码



我有一个在软件发布期间运行的bash脚本,用于验证所有源文件是否包含版权和许可证标头。 时不时地,我必须向它添加新的文件扩展名,因此我的"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的实际调用是静默的,表明未找到匹配的任何内容。 这令人费解,因为 echo'd 版本表明 find 命令的构造完全符合我的预期。 (如果我将该回显输出复制粘贴到 shell,它确实会返回文件列表。
  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 文件,以确保不会发生早期通配):

* 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 的通配