x行未満のファイルを削除する簡単な方法

x行未満のファイルを削除する簡単な方法

bashのx行の下のディレクトリ内のすべてのファイルを削除するための迅速で複雑ではない方法はありますか?

答え1

これはPOSIXソリューションであり、理解するのはとても簡単です。

find . -type f -exec awk -v x=10 'NR==x{exit 1}' {} \; -exec echo rm -f {} \;

のようにスティーブンの答え、削除にecho満足すれば削除されます。


Unix/Linux 初心者向けに書かれた説明:

点は.現在のディレクトリを表します。 findファイルとディレクトリは で繰り返し検出され、.これを行うことができます。

-typefindそのうちの一つ予備選挙;これは繰り返し(含まれている)見つかったすべてのファイルとディレクトリに対して実行されるテストであり.、その行の残りの基本項目は結果が「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述語をサポートする実装を想定します-readablefindサポートされていない場合は削除すると、ファイルを読み取れないというエラーメッセージが表示されるか、または置き換えられます-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) 

関連情報