如何在 bash 中使用程序参数从查找中排除文件/目录?

如何在 bash 中使用程序参数从查找中排除文件/目录?

我的发现看起来很简单:

find . -type f

我试图弄清楚如何根据程序参数行排除某些文件或目录。

bash myscript.sh -excl a b c d 

其中a, b, c, d或选项的任何下一个参数excl是正则表达式,引用我想要排除的某些文件或目录。

所以如果我这样调用程序:

bash myscript.sh -excl *.sh somedir

我只是想 find 忽略 somedir 目录和所有带有.sh扩展名的文件。这在 bash 中可能吗?

答案1

使用bash数组的解决方案:

#!/bin/bash

declare -a find_arguments=( -type f )

for arg; do

  find_arguments+=( ! -name "$arg" )

done

find . "${find_arguments[@]}"

如果您确实想要正则表达式,则改为-name但从-regex您的示例来看,您似乎想要通配符。 (顺便说一句,-regex不是 POSIX,但受 GNU 支持find。)

演示

touch {a,b,c}{x,y,z}
./myscript.sh 'a*' '*z'

输出:

./bx
./by
./cx
./cy

我省略了命令行解析-excl等,因为您没有明确脚本的命令行选项通常是什么样子,如果确实如此,-excl您可以简单地检查它([[ "$1" = -excl ]])然后shift

答案2

-not -name是的,如果脚本有第二个参数,您可以添加一个:

#!/bin/bash 

targetDir="$1"
exclude="$2"

findString=" '$targetDir'"

if [[ ! -z "$exclude" ]]; then
        findString="$findString -not -name '$exclude'"
fi
eval "find $findString"

例如:

$ ls
file1  file1.sh  file2  file2.sh  file3.sh  file4.sh  file5.sh
$ foo.sh .
.
./file1
./file2
./file1.sh
./file4.sh
./file3.sh
./file5.sh
./file2.sh
$ foo.sh . '*sh'
.
./file1
./file2

如果您希望能够定义多个要排除的模式:

#!/bin/bash 

targetDir="$1"
findString=" '$targetDir'"
shift
exclude="'$1'"
shift
for i in "$@"; do
        exclude="$exclude -a -not -name '$i'";
done
if [[ ! -z "$exclude" ]]; then
        findString="$findString -not -name $exclude"
fi
eval "find $findString"

相关内容