我想使用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 ___”?
谢谢!
答案 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}
没有替换项目之间的空格。