[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
。もしそうなら、代わりに次のいずれかを使用してください。+?
\.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
- もちろん、1行にすべて入れることができます(
\
最初の行の最後の項目を削除してください)。 -regextype posix-egrep
正確にうまく機能しているようです-regextype posix-extended
。find
あなたのバージョンがそれをサポートしていない場合、またはを-delete
使用してください。-exec rm -- {} +
-exec rm -- {} ';'
- 最上位ディレクトリのみを検索するには、を使用します
-maxdepth 1
。