我需要递归遍历一个目录并删除扩展名为.pdf和.doc的所有文件,我正在设法循环遍历一个目录,但没有设法过滤带有上述文件扩展名的文件。
到目前为止我的代码
#/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
我需要帮助来完成代码,因为我无处可去。
答案 0 :(得分:181)
作为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的解决方案:
find /tmp \( -name '*.pdf' -or -name '*.doc' \) -print0 | xargs -0 rm
(此处需要使用转义括号使-print0
适用于or
个条款。)
GNU和* BSD查找也有一个-delete
操作,如下所示:
find /tmp \( -name '*.pdf' -or -name '*.doc' \) -delete
答案 1 :(得分:126)
find
就是为此做出的。
find /tmp -name '*.pdf' -or -name '*.doc' | xargs rm
答案 2 :(得分:51)
没有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
请注意,这需要bash≥4.0(或zsh不shopt -s globstar
,或ksh set -o globstar
而不是shopt -s globstar
)。此外,在bash< 4.3中,这遍历了到目录和目录的符号链接,这通常是不可取的。
答案 3 :(得分:25)
如果你想以递归方式做某事,我建议你使用递归(是的,你可以使用堆栈等来做,但是嘿)。
recursiverm() {
for d in *; do
if [ -d "$d" ]; then
(cd -- "$d" && recursiverm)
fi
rm -f *.pdf
rm -f *.doc
done
}
(cd /tmp; recursiverm)
尽管如此,find
可能是一个比较好的选择。
答案 4 :(得分:12)
以下是使用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
答案 5 :(得分:10)
这不会直接回答您的问题,但您可以使用单行解决问题:
find /tmp \( -name "*.pdf" -o -name "*.doc" \) -type f -exec rm {} +
某些版本的find(GNU,BSD)有一个-delete
操作,您可以使用该操作而不是调用rm
:
find /tmp \( -name "*.pdf" -o -name "*.doc" \) -type f -delete
答案 6 :(得分:6)
此方法可以很好地处理空间。
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
}
答案 7 :(得分:2)
对于bash(从4.0版开始):
shopt -s globstar nullglob dotglob
echo **/*".ext"
这就是全部 尾随扩展名" .ext"在那里选择具有该扩展名的文件(或目录)。
选项globstar激活**(递归搜索) 选项nullglob在没有匹配文件/目录时删除* 选项dotglob包含以点(隐藏文件)开头的文件。
请注意,在bash 4.3之前,**/
还会遍历指向不可取的目录的符号链接。
答案 8 :(得分:1)
以下函数将递归遍历\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
答案 9 :(得分:1)
这是我知道的最简单方法:
rm **/@(*.doc|*.pdf)
**
使此工作递归进行
@(*.doc|*.pdf)
查找以pdf或doc结尾的文件
易于将rm
替换为ls
来进行安全测试
答案 10 :(得分:0)
没有理由将find
的输出传递到另一个实用程序中。 find
内置了一个-delete
标志。
find /tmp -name '*.pdf' -or -name '*.doc' -delete
答案 11 :(得分:0)
提供的for答案将不包含以开头的文件或目录。以下对我有用:
#/bin/sh
getAll()
{
local fl1="$1"/*;
local fl2="$1"/.[!.]*;
local fl3="$1"/..?*;
for inpath in "$1"/* "$1"/.[!.]* "$1"/..?*; do
if [ "$inpath" != "$fl1" -a "$inpath" != "$fl2" -a "$inpath" != "$fl3" ]; then
stat --printf="%F\0%n\0\n" -- "$inpath";
if [ -d "$inpath" ]; then
getAll "$inpath"
#elif [ -f $inpath ]; then
fi;
fi;
done;
}
答案 12 :(得分:-1)
只做
find . -name '*.pdf'|xargs rm
答案 13 :(得分:-1)
以下将以递归方式遍历给定目录并列出所有内容:
for d in /home/ubuntu/*;
do
echo "listing contents of dir: $d";
ls -l $d/;
done
答案 14 :(得分:-2)
如果可以更改用于运行命令的外壳,则可以使用ZSH来完成工作。
#!/usr/bin/zsh
for file in /tmp/**/*
do
echo $file
done
这将循环遍历所有文件/文件夹。