迭代文件并排除具有特定名称模式的文件 Shell

迭代文件并排除具有特定名称模式的文件 Shell

如何迭代当前目录中的文件并排除某些具有特定名称模式的文件?该解决方案必须兼容 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.txtor 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

相关内容