Bash

在變數中查找具有文件名模式的 xargs rm

  • April 4, 2020

像這樣的命令:

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:我使用了一個數組,因為我有多個文件副檔名。

你的數組分配,

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[@]}""$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

引用自:https://unix.stackexchange.com/questions/577946