如何通过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