递归查找文件类型的列表
递归查找文件类型的列表
我想使用bash删除目录中不在文件扩展名关联数组中的所有文件(例如,删除不是图像文件的所有文件)。\n这个问题非常明确地回答了如何对单个文件扩展名执行此操作,但我不确定如何对整个列表执行此操作。\n目前我正在使用以下方法:\n
for f in $(find . -type f ! -name '*.png' -and ! -name '*.jpg' ); do rm "$f"; done
\n但是在括号中添加大量的“-and -name \'*.aaa\'”似乎很丑陋。\n有没有办法像这样向find
传递关联数组:\n
declare -A allowedTypes=([*.png]=1 [*.jpg]=1 [*.gif]=1)
\n还是我只需要添加很多“-and ! -name ___”?\n谢谢!
递归地寻找文件类型列表的问题出现的原因是需要根据给定的文件后缀来过滤文件。解决方法是使用不同的代码片段来实现。
第一个代码片段支持多级后缀,例如`tar.gz`。它使用了`find`命令、正则表达式和允许的后缀列表`allowedTypes`。
allowedTypes=(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}"`并没有替换项目之间的空格。
在上述内容中,出现了寻找文件类型列表(Recursively looking for a list of file types)这个问题,并提供了解决方法。
问题的出现原因是最初使用了find
命令来解决问题,但实际上并不需要使用find
。在bash
中,通配符支持足够满足需求。可以通过设置bash
的扩展通配符选项extglob
来获取不以指定扩展名结尾的递归路径下的文件名。
解决方法如下:
1. 使用shopt
命令设置扩展选项:shopt -s extglob nullglob globstar
2. 构建通配符表达式以排除*.png
、*.jpg
和*.gif
类型的文件。使用数组fileList
存储通配符结果:fileList=(**/!(*.jpg|*.gif|*.png))
3. 打印实际文件:printf '%s\n' "${fileList[@]}"
4. 如果需要删除所有识别到的文件,可以使用rm
命令: rm -- **/!(*.jpg|*.gif|*.png)
此外,对于使用globstar
的bash
v4及以上版本的用户,可以直接使用bash
的扩展通配符功能。而对于macOS用户,需要安装bash
v4以上版本,因为苹果只提供了bash
v3.2左右的版本。
对于文件名或扩展名中包含大写字母的情况,可以使用nocaseglob
选项来忽略大小写匹配:shopt -s nocaseglob
。