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

Kri*_*ris 3 bash find rm

像这样的命令:

find /directory -type f -name "*.txt" -print | xargs rm
Run Code Online (Sandbox Code Playgroud)

删除.txt目录和子目录中的每个文件,就可以了。但是,如果我们为文件扩展名创建一个变量或数组,然后放入find,例如,

TXT=(*.txt)
for ii in ${TXT[@]}; do
  find /directory -type f -name $TXT -print | xargs rm
done
Run Code Online (Sandbox Code Playgroud)

此命令不会删除.txt子目录中的文件。为什么?如何更改第二个代码以删除子目录中的文件?

PS:我使用了一个数组,因为我有多个文件扩展名。

Kus*_*nda 7

你的数组分配,

TXT=(*.txt)
Run Code Online (Sandbox Code Playgroud)

*.txt模式扩展到当前目录中与该模式匹配的列表文件名。外壳将在分配时执行此操作。这不是你想要的。您想提供find文字 string *.txt,如下所示:

pattern='*.txt'
find /directory -type f -name "$pattern" -exec rm {} +
Run Code Online (Sandbox Code Playgroud)

在这里,我也摆脱了xargs rm,而是rm直接从find. 的大多数当前实现find可以使用非标准-delete代替-exec rm {} +

pattern='*.txt'
find /directory -type f -name "$pattern" -delete
Run Code Online (Sandbox Code Playgroud)

请注意,这里不需要循环,因为我们只处理单个模式。另请注意,"$pattern"在调用中引用 offind很重要,否则模式将在find启动之前被当前目录中的所有匹配文件名替换。

对于几种模式,您可以执行如下循环:

patterns=( '*.txt' '*.tmp' )
for pattern in "${patterns[@]}"; do
    find /directory -type f -name "$pattern" -delete
done
Run Code Online (Sandbox Code Playgroud)

数组赋值中的引用是必不可少的,因为它会阻止 shell 使用这些模式作为文件名通配模式。出于同样的原因,引用"${patterns[@]}""$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
Run Code Online (Sandbox Code Playgroud)

在上面的脚本中,最后执行的实际命令将是

find /directory -type f '(' -name '*.txt' -o -name '*.tmp' ')' -delete
Run Code Online (Sandbox Code Playgroud)

...这将删除所有具有文件名后缀.txt .tmp目录中或目录下任何位置的常规文件/directory