像这样的命令:
find /directory -type f -name "*.txt" -print | xargs rm
删除.txt
目录和子目录中的每个文件,就可以了。但是,如果我们为文件扩展名创建一个变量或数组,然后放置find
,例如,
TXT=(*.txt)
for ii in ${TXT[@]}; do
find /directory -type f -name $TXT -print | xargs rm
done
此命令不会删除.txt
子目录中的文件。为什么?如何更改第二段代码以删除子目录中的文件?
PS:我使用了一个数组,因为我有多个文件扩展名。
答案1
你的数组分配,
TXT=(*.txt)
会将*.txt
模式扩展到当前目录中与该模式匹配的文件名列表。 shell 会在分配时执行此操作。这不是你想要的。您想要给出find
文字 string *.txt
,如下所示:
pattern='*.txt'
find /directory -type f -name "$pattern" -exec rm {} +
在这里,我也摆脱了xargs rm
,而是rm
直接从执行find
。大多数当前的实现find
可以使用非标准-delete
来代替-exec rm {} +
:
pattern='*.txt'
find /directory -type f -name "$pattern" -delete
请注意,这里不需要循环,因为我们只处理单个模式。另请注意,"$pattern"
调用中的引号find
很重要,否则该模式将在启动前被当前目录中所有匹配的文件名替换find
。
对于多种模式,您可以像这样执行循环:
patterns=( '*.txt' '*.tmp' )
for pattern in "${patterns[@]}"; do
find /directory -type f -name "$pattern" -delete
done
数组赋值中的引号至关重要,因为它可以阻止 shell 将模式用作文件名匹配模式。出于同样的原因,引用"${patterns[@]}"
and 也同样重要。"$pattern"
另一种方法是仅对 进行一次调用find
,即使您有多个模式。如果/directory
目录层次结构很大,这会大大加快速度。以下代码通过构建一系列-name
测试来find
实现这一点:
patterns=( '*.txt' '*.tmp' )
name_tests=( )
for pattern in "${patterns[@]}"; do
name_tests+=( -o -name "$pattern" )
done
# "${name_tests[@]:1}" removes the initial "-o", which shouldn't be there.
name_tests=( '(' "${name_tests[@]:1}" ')' )
find /directory -type f "${name_tests[@]}" -delete
在上面的脚本中,最后执行的实际命令将是
find /directory -type f '(' -name '*.txt' -o -name '*.tmp' ')' -delete
...这将删除所有具有文件名后缀的常规文件.txt
或者 .tmp
目录中或目录下的任何位置/directory
。