如何通过recursion循环目录来删除具有特定扩展名的文件

我需要循环遍历一个目录recursion和删除所有文件的扩展名为.pdf和.doc,我pipe理循环通过目录recursion,但不pipe理上述文件扩展名过滤文件。

我的代码到目前为止

#/bin/sh SEARCH_FOLDER="/tmp/*" for f in $SEARCH_FOLDER do if [ -d "$f" ] then for ff in $f/* do echo "Processing $ff" done else echo "Processing file $f" fi done 

我需要帮助来完成代码,因为我没有得到任何地方。

find就是为了这个。

 find /tmp -name '*.pdf' -or -name '*.doc' | xargs rm 

作为mouviciel的答案的后续,你也可以做这个for循环,而不是使用xargs。 我经常发现xargs麻烦,特别是如果我需要在每次迭代中做更复杂的事情。

 for f in $(find /tmp -name '*.pdf' -or -name '*.doc'); do rm $f; done 

正如许多人所评论的,如果文件名中有空格,这将会失败。 您可以通过临时将IFS(内部字段分隔符)设置为换行符来解决此问题。 如果文件名中有通配符\[?* 您可以通过暂时禁用通配符扩展(globbing)来解决此问题。

 IFS=$'\n'; set -f for f in $(find /tmp -name '*.pdf' -or -name '*.doc'); do rm "$f"; done unset IFS; set +f 

如果你的文件名中有换行符,那么这也行不通。 你最好用基于xargs的解决scheme:

 find /tmp \( -name '*.pdf' -or -name '*.doc' \) -print0 | xargs -0 rm 

(转义括号在这里是要求-print0适用于这两个or子句。)

GNU和* BSD发现也有一个-delete行为,看起来像这样:

 find /tmp \( -name '*.pdf' -or -name '*.doc' \) -delete 

没有find

 for f in /tmp/* tmp/**/* ; do ... done; 

/tmp/*是dir中的文件, /tmp/**/*是子文件夹中的文件。 您可能需要启用globstar选项( shopt -s globstar )。 所以对于这个问题,代码应该是这样的:

 shopt -s globstar for f in /tmp/*.pdf /tmp/*.doc tmp/**/*.pdf tmp/**/*.doc ; do rm "$f" done 

请注意,这需要shopt -s globstar (或者不使用zsh,或者使用set -o globstar而不是shopt -s globstar )。 此外,在bash <4.3中,这遍历了目录以及目录的符号链接,这通常是不可取的。

如果你想recursion地做一些事情,我build议你使用recursion(是的,你可以使用堆栈等等,但是嘿)。

 recursiverm() { for d in *; do if [ -d "$d" ]; then (cd -- "$d" && recursiverm) fi rm -f *.pdf rm -f *.doc done } (cd /tmp; recursiverm) 

这就是说, find可能是一个更好的select,因为已经build议。

这是一个使用shell( bash )的例子:

 #!/bin/bash # loop & print a folder recusively, print_folder_recurse() { for i in "$1"/*;do if [ -d "$i" ];then echo "dir: $i" print_folder_recurse "$i" elif [ -f "$i" ]; then echo "file: $i" fi done } # try get path from param path="" if [ -d "$1" ]; then path=$1; else path="/tmp" fi echo "base path: $path" print_folder_recurse $path 

这不直接回答你的问题,但你可以用一行代码解决你的问题:

 find /tmp \( -name "*.pdf" -o -name "*.doc" \) -type f -exec rm {} + 

find(GNU,BSD)的某些版本有一个可以用来代替调用rm-delete操作:

 find /tmp \( -name "*.pdf" -o -name "*.doc" \) -type f -delete 

这个方法处理空间很好。

 files="$(find -L "$dir" -type f)" echo "Count: $(echo -n "$files" | wc -l)" echo "$files" | while read file; do echo "$file" done 

编辑,逐个修复

 function count() { files="$(find -L "$1" -type f)"; if [[ "$files" == "" ]]; then echo "No files"; return 0; fi file_count=$(echo "$files" | wc -l) echo "Count: $file_count" echo "$files" | while read file; do echo "$file" done } 

对于bash(从4.0版本开始):

 shopt -s globstar nullglob dotglob echo **/*".ext" 

就这样。
尾部扩展名“.ext”用于select带有扩展名的文件(或目录)。

选项globstar激活**(recursionsearch)。
选项nullglob在不匹配文件/目录时删除*。
选项dotglob包括以点开始的文件(隐藏文件)。

注意,在bash 4.3之前, **/还会遍历不符合要求的目录的符号链接。

以下函数将recursion遍历\home\ubuntu目录(ubuntu下的整个目录结构)中的所有目录,并在else块中应用必要的检查。

 function check { for file in $1/* do if [ -d "$file" ] then check $file else ##check for the file if [ $(head -c 4 "$file") = "%PDF" ]; then rm -r $file fi fi done } domain=/home/ubuntu check $domain 

做就是了

 find . -name '*.pdf'|xargs rm 

以下将循环遍历给定的目录并列出所有的内容:

for d in /home/ubuntu/*; do echo "listing contents of dir: $d"; ls -l $d/; done