递归查找文件类型列表

时间:2018-08-05 13:06:44

标签: bash search filter associative-array

我想使用bash删除目录中所有不在文件扩展名关联数组中的文件。 (例如,删除目录中不是图像文件的所有文件)

This question非常清楚地回答了如何对单个文件扩展名执行此操作,但是我不确定如何对整个列表执行此操作。

当前我正在this

for f in $(find . -type f ! -name '*.png' -and ! -name '*.jpg' ); do rm "$f"; done

但是为每种文件类型在括号内添加大量的“-和-name'* .aaa'”列表似乎很丑。

有没有一种方法可以传递find这样的关联数组

declare -A allowedTypes=([*.png]=1 [*.jpg]=1 [*.gif]=1)

还是我只需要添加很多“-和!-name ___”?

谢谢!

2 个答案:

答案 0 :(得分:3)

完全不需要使用ET.setFocusableInTouchMode(true); 到头的整个想法。 find中的shell glob支持足以满足此要求。 bash外壳程序提供了扩展的glob支持选项,通过该选项,您可以在不以您要忽略的扩展名结尾的递归路径下获取文件名。

扩展选项为bash,需要使用extglob选项进行设置,如下所示。另外,您可以使用更多选项,例如shopt,其中不匹配的glob会被完全清除,而用一组零个单词代替。并且nullglob允许遍历所有目录

globstar

现在,您要做的就是形成全局表达式,以排除类型为shopt -s extglob nullglob globstar *.png*.jpg的文件,您可以按照以下方式进行操作。我们使用数组填充全局结果,因为当正确引用和扩展它们时,带有特殊字符的文件名将保持不变

*.gif

选项fileList=(**/!(*.jpg|*.gif|*.png)) 是通过子文件夹递归的,而**是否定操作,不包括其中列出的任何文件扩展名。现在要打印实际文件,只需执行

!()

例如,如果您打算删除所有已标识的文件,则无需将全局结果存储在数组中。在编写需要使用glob结果的简单shell脚本时,可以使用数组方法。但是对于删除文件的情况,可以使用printf '%s\n' "${fileList[@]}" 命令。

首先,您可以检查返回的文件是否符合预期的 ,一旦确认,就可以在表达式上使用rm。使用rm查看文件是否按预期列出

ls

现在,在确认要删除的文件后,ls -1 -- **/!(*.jpg|*.gif|*.png) 自担风险。

rm

答案 1 :(得分:1)

假设allowedTypes仅包含受信任的输入和仅有效的后缀。

第一个代码段支持多级后缀,例如tar.gz。它使用find,正则表达式和允许的后缀allowedTypes的列表。

allowedTypes=(png gif jpg)

# keepTypes='png|gif|jpg'
keepTypes="$(echo "${allowedTypes[@]}" | tr ' ' '|')"

find . -type f -regextype awk ! -iregex '(.*).('"$keepTypes"')' -exec echo rm {} \;

如果要保留关联数组,则可以使用以下代码段。 需要更多工作来支持多级文件后缀。

declare -A allowedTypes=([*.png]=1 [*.jpg]=1 [*.gif]=1)

keepTypes="$(echo "${!allowedTypes[@]}" | tr ' ' '|' | tr -d '.*')"

如果有一种方法可以用内置工具代替tr来替换分隔符,那很好,但我没有找到。 ${allowedTypes[@]//\ /test}没有替换项目之间的空格。