
[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)
!
これは、( )に一致しないすべてのファイル/ディレクトリ名を出力し、その後に sの間に[[:digit:][:upper:]]
0 個または 1 個[[:digit:][:upper:]]
の 4 個が続き、その後に拡張子の前に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
。