正規表現によるファイルの削除

正規表現によるファイルの削除

[0-9A-Z]{1,2}_\d{4}_\w+?\.datたとえば、A1_2001_pm23aD.dat同じ名前のファイルを保持し、K_1998_12.dat残りを削除したいと思います。

ただし、lsコマンドrmはこれらの正規表現をサポートしません。どうすればいいですか?

答え1

拡張グローブを使用してください。

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

これは!()と一致しないすべてのファイル/ディレクトリ名を印刷し、[[:digit:][:upper:]]その後に0または1、sの間に4 [[:digit:][:upper:]]、拡張子の前に1つ以上が続きます。再帰的に検索するには:[[: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。もしそうなら、代わりに次のいずれかを使用してください。+?\.datfoobarfoobarfoobarA1_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
  • もちろん、1行にすべて入れることができます(\最初の行の最後の項目を削除してください)。
  • -regextype posix-egrep正確にうまく機能しているようです-regextype posix-extended
  • findあなたのバージョンがそれをサポートしていない場合、またはを-delete使用してください。-exec rm -- {} +-exec rm -- {} ';'
  • 最上位ディレクトリのみを検索するには、を使用します-maxdepth 1

関連情報