
我想保留名稱匹配的文件[0-9A-Z]{1,2}_\d{4}_\w+?\.dat
,例如,A1_2001_pm23aD.dat
,K_1998_12.dat
,並刪除其餘文件。
但是,ls
和rm
命令不支援此類正規表示式。我怎樣才能做到這一點?
答案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
.