如何迭代当前目录中的文件并排除某些具有特定名称模式的文件?该解决方案必须兼容 POSIX。
假设要排除的文件遵循以下模式:test[0-9].txt 和 work-.*(使用正则表达式)。
到目前为止我的代码:
for file in *
do
if test "$file" != "test[0-9].txt" -o "$file" != "work-.*"
then
echo "$file"
fi
done
目前输出是工作目录中的所有文件。我很确定测试中的模式匹配不正确,但我该如何修复它?
答案1
if test "$file" != "test[0-9].txt" -o "$file" != "work-.*"
该test
实用程序不进行模式匹配。为此,您需要 Ksh/Bash/Zsh[[ ]]
构造(至少在 Bash 中,不需要引用该模式)。所以:
for file in *; do
if [[ "$file" != test[0-9].txt && "$file" != work-.* ]]; then
echo "$file"
fi
done
将打印hello.txt
, 如果存在,但不打印test1.txt
or work-.foo
。
请注意,您需要和代替或者在那里,如 (x ≠ a或者x ≠ b) 将匹配任何 x。
看:
在严格的 POSIX sh 中,您需要使用case
以下方法进行模式匹配:
for file in *; do
case $file in
test[0-9].txt|work-.*) false;;
*) echo "$file";;
esac
done
请注意,如果您想匹配 后的多个数字test
(如 中所示)test123.txt
,那么您将需要 ksh 样式的扩展 glob 和test+([0-9]).txt
(并shopt -s extglob
在 Bash 中让它们在所有上下文中工作)。尽管就像库萨拉南达(Kusalananda)指出的那样,如果你走那条路,你也可以这样做:
for file in !(test[0-9].txt|work-.*); do
echo "$file"
done
答案2
您可以使用所有可能的组合来创建一个字符串:
all=:
for thing in *test[0-9].txt work-.*; do
all=$all$thing:
done
if [[ "$all" == *:"$file":* ]]; then
# it is in the list