bashのx行の下のディレクトリ内のすべてのファイルを削除するための迅速で複雑ではない方法はありますか?
答え1
これはPOSIXソリューションであり、理解するのはとても簡単です。
find . -type f -exec awk -v x=10 'NR==x{exit 1}' {} \; -exec echo rm -f {} \;
のようにスティーブンの答え、削除にecho
満足すれば削除されます。
Unix/Linux 初心者向けに書かれた説明:
点は.
現在のディレクトリを表します。 find
ファイルとディレクトリは で繰り返し検出され、.
これを行うことができます。
-type
find
そのうちの一つ予備選挙;これは繰り返し(含まれている)見つかったすべてのファイルとディレクトリに対して実行されるテストであり.
、その行の残りの基本項目は結果が「true」の場合にのみ評価されます。
この特別なケースでは、次のことを処理する場合にのみ一般ファイル、ディレクトリや他のもの(ブロックデバイスなど)ではありません。
マスター-exec
ノードはfind
外部コマンドを呼び出し、外部コマンドが正常に終了した場合にのみ次のマスターノードに進みます(終了ステータスは '0')。{}
コマンドによって「考慮された」ファイル名に置き換えられましたfind
。したがって、最初の-exec
呼び出しは、各ファイルに対して順番に実行される次のシェルコマンドと同じです。
awk -v x=10 'NR==x{exit 1}' ./somefilename
awkはそれ自体で完全な言語です。CSVなどの区切りテキストファイルを処理するように設計されています。 Awk条件とコマンド(単一引用符で囲まれ、文字で始まるNR
)はテキストファイルの各行で実行されます。 (暗黙のループ。)
Awkを完全に学ぶには強くお勧めします薄暗い光チュートリアルしかし、上記のコマンドで使用されているAwk機能について説明します。
Awkフラグを-v
使用すると、Awkコマンドを実行する前に(ファイルの各行ごとに)Awk変数を(一度)設定できます。この場合はx
に設定しました10
。
NR
「を参照する特別なAwk変数です。窒素現在の数量右エコ。つまり、ループの特定のパスで私たちが見ている行番号です。
(参考にしてください。はい珍しいが、他の"を使用することが可能です。右エココードSによって設定されたデフォルトの改行文字より "eparator" がRS
。 以下は、レコード区切り記号を使用した再生の例です。)
awkスクリプトには通常、次のものが含まれます。状況(中括弧外)行動(中括弧内に。)複合条件と複合演算があり、基本条件(true)と基本動作(print)がありますが、心配する必要はありません。
これ状況「この行は10ですか?」です。そうであれば、ゼロ以外の終了状態で終了します。これは、シェルスクリプトで「コマンドの終了に失敗しました」を意味します。
だからAwkコマンドは終了する唯一の方法です正常に10行目に達する前にファイルの終わりに達したかどうかを示します。
したがって、awkスクリプトが正常に終了すると、10行未満のファイルがあることを意味します。
次-exec
の呼び出し(削除された場合)は、次を実行してecho
すべてのファイル(基本評価のこの時点まで)を削除します。find
rm -f ./somefilename
答え2
find
述語をサポートする実装を想定します-readable
(find
サポートされていない場合は削除すると、ファイルを読み取れないというエラーメッセージが表示されるか、または置き換えられます-exec test -r {} \;
)。
x=10 find . -type f -readable -exec sh -c '
for file do
lines=$(wc -l < "$file") && [ "$((lines))" -lt "$x" ] && echo rm -f "$file"
done' sh {} +
echo
満足のいくものを削除してください。
これは重要なので、特に効率的ではありません。みんなx
行があり、最初のファイルでのみ停止し、各ファイルに対して1つwc
(おそらく1つrm
)のコマンドを実行します。
GNUを使用すると、awk
次のように効率を向上できます。
x=10
find . -type f -readable -exec awk -v x="$x" -v ORS='\0' '
FNR == x {nextfile}
ENDFILE {if (FNR < x) print FILENAME}' {} +|
xargs -r0 echo rm -f
(もう一度言っても満足していればecho
削除してください)。
以下と同じperl
:
x=10 find . -type f -readable -exec perl -Tlne '
if ($. == $ENV{x}) {close ARGV}
elsif (eof) {print $ARGV; close ARGV}' {} +
print
気に入ったら変えてくださいunlink
。
答え3
完全性のためにAWKに加えて、GNU sedを使用して同じ結果を得ることもできます。
find . -type f -exec sed 11q1 '{}' ';' -exec echo rm -f '{}' ';'
その結果、コマンドラインがよりきれいになりました。
説明する
11 - is the address, i.e. "the eleventh line"
q - is for _q_uit (abort the execution)
1 - is the exit code parameter for q (GNU sed extension)