透過正規表示式刪除文件

透過正規表示式刪除文件

我想保留名稱匹配的文件[0-9A-Z]{1,2}_\d{4}_\w+?\.dat,例如,A1_2001_pm23aD.datK_1998_12.dat,並刪除其餘文件。

但是,lsrm命令不支援此類正規表示式。我怎樣才能做到這一點?

答案1

使用擴充的 glob:

shopt -s extglob
printf '%s\n' !([[:digit:][:upper:]]?([[:digit:][:upper:]])_[[:digit:]][[:digit:]][[:digit:]][[:digit:]]_+([[:alnum:]]).dat)

這將列印所有不 ( !) 匹配的檔案/目錄名稱,[[:digit:][:upper:]]後面跟著零或一,後面跟著 s之間的[[:digit:][:upper:]]4 ,然後在擴展名之前跟隨一個或多個。 如果你想遞歸搜尋:[[:digit:]]_[[:alnum:]].dat

shopt -s globstar
shopt -s extglob
printf '%s\n' **/!([[:digit:][:upper:]]?([[:digit:][:upper:]])_[[:digit:]][[:digit:]][[:digit:]][[:digit:]]_+([[:alnum:]]).dat)

或者,使用gnu find(您可以使用正規表示式):

find . -regextype egrep ! -regex '.*/[[:digit:][:upper:]]{1,2}_[[:digit:]]{4}_[[:alnum:]]+\.dat$'

答案2

有很多方法可以做到這一點。您可以使用理解正規表示式的腳本語言。例如,在 Perl 中:

perl -le 'unlink(grep(!/[0-9A-Z]{1,2}_\d{4}_\w+?.dat/,@ARGV))' *

這將查找所有文件(不是子目錄) 在目前目錄中,收集那些與正規表示式不符的內容並將其刪除。

您也可以使用 bash 執行類似的操作,只需將正規表示式轉換為 POSIX ERE:

for f in *; do 
    [[ "$f" =~ [0-9A-Z]{1,2}_[0-9]{4}_[a-zA-Z0-9]+.dat ]] || rm "$f"; 
done

請注意,在您的正規表示式中,\w+?.dat將嘗試匹配盡可能小的字母數字字串任何字元dat。我不明白你為什麼想+?在這裡使用,而你可能想使用\.dat.我猜您可能還想確保整個文件名匹配,以便類似的內容foobarfoobarfoobarA1_2001_pm23aD.datfoobarfooabr也被刪除。如果是這樣,請改用其中一個:

perl -le 'unlink(grep(!/^[0-9A-Z]{1,2}_\d{4}_\w+\.dat$/,@ARGV))' *

或者

for f in *; do 
    [[ "$f" =~ ^[0-9A-Z]{1,2}_[0-9]{4}_[a-zA-Z0-9]+.dat$ ]] || rm "$f"; 
done

最後,要刪除目錄,您可以執行以下操作:

for f in *; do 
    [[ "$f" =~ ^[0-9A-Z]{1,2}_[0-9]{4}_[a-zA-Z0-9]+.dat$ ]] || rm -rf "$f"; 
done

答案3

你可以這樣做find

find . -regextype posix-extended \
            -type f ! -regex '.*/[0-9A-Z]{1,2}_[[:digit:]]{4}_[[:alnum:]_]+?\.dat' -delete
  • 當然,您可以將其全部放在一行中(刪除\第一行末尾的 )。
  • -regextype posix-egrep似乎工作完全一樣好-regextype posix-extended
  • 如果您的版本find不支持-delete,請使用-exec rm -- {} +-exec rm -- {} ';'
  • 如果您只想搜尋頂級目錄,請使用-maxdepth 1.

相關內容