在变量中查找具有文件名模式的 xargs rm

在变量中查找具有文件名模式的 xargs rm

像这样的命令:

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

相关内容