我有一个在软件发布期间运行的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'
基本上,有两个问题:
echo
行生成任何输出; find
的实际调用是静默的,表示没有找到匹配的内容。这很令人费解,因为echo'd版本表明find
命令的构建正是我所期望的。 (如果我将回显输出复制粘贴到shell,它会返回一个文件列表。)for
循环正在扩展$ _fs的值,如果当前目录中的文件与$ _fs匹配(例如'check-license.sh','* .sh ')我想要的结果是让$ FILEMASKS中的所有文件掩码都使我的find
命令无法扩展。 [更新] 我刚刚找到了解决#2的方法:我从*.
变量中的每个条目的开头删除FILEMASKS
,然后添加它在find
命令中返回 in situ 。所以,只剩下#1了。但我仍然有兴趣看到#2的其他解决方案。
答案 0 :(得分:2)
您可以使用数组作为掩码列表来规避这些问题。
这样的事情:
#! /bin/bash
exts=('*.txt' '*.jpg')
for ext in "${exts[@]}" ; do
echo "* For mask [$ext]:"
find . -iname "$ext"
done
我得到这个输出(toplevel目录包含一个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'
的文件与文件名中的单引号。 (并且因为*
和其他的globbing字符没有被引用,所以在参数传递给find
之前,你将通过shell进行通配。)