回答:
理解するのが非常に簡単なPOSIXソリューションを次に示します。
find . -type f -exec awk -v x=10 'NR==x{exit 1}' {} \; -exec echo rm -f {} \;
以下のようにステファンの答え、削除echo削除されるものとするときに幸せを。
ドット.は現在のディレクトリを表します。 find内.でファイルとディレクトリを再帰的に検索し、それらを使用して処理を実行できます。
-type一つであるfindの予備選挙。これは、(内で.)再帰的に検出されるファイルとディレクトリごとに実行されるテストであり、行の残りのプライマリは、これが「true」になる場合にのみ評価されます。
この特定のケースでは、ディレクトリなどではなく通常のファイル(ブロックデバイスなど)を扱っている場合にのみ続行します。
-exec(の主はfind)外部コマンドを呼び出し、外部コマンドの終了が正常に(「0」の終了状態)場合のみ、次のプライマリに移行します。{}で「とみなさ」されているファイル名に置き換えられているfindコマンド。したがって、最初の-exec呼び出しは、ファイルごとに順番に実行される次のシェルコマンドと同等です。
awk -v x=10 'NR==x{exit 1}' ./somefilename
Awkはそれ自体が言語全体であり、 CSVなどの区切られたテキストファイルを処理するために設計されています。Awkの条件文とコマンド(一重引用符で囲まれ、文字で始まるNR)は、テキストファイルのすべての行に対して実行されます。(暗黙のループ。)
Awkを完全に学習するには、Grymoireチュートリアルを強くお勧めしますが、上記のコマンドで使用されるAwkの機能について説明します。
-vAwkへのフラグにより、Awkコマンドが実行される前に(ファイルの各行に対して)Awk変数を(1回だけ)設定できます。この場合、に設定xし10ます。
NR特別なawkの変数を参照している「Nの現在のアンバーのR ECORD。」つまり、ループの特定のパスで見ている行番号です。
(通常ではありませんが、を設定することにより、改行文字のデフォルトとは異なる " R ecord S eparator" を使用することができます。 ここでは、レコード区切り記号を使用した例を示します。)RS
Awkスクリプトは一般に、アクション(中括弧内)と組み合わせた条件(中括弧外)で構成されます。複合条件と複合アクションがあり、デフォルト条件(true)とデフォルトアクション(印刷)がありますが、それらを気にしないでください。
ここでの条件は、「これは10行目ですか」です。この場合、ゼロ以外の終了ステータスで終了します。これは、シェルスクリプトでは「コマンドの終了に失敗した」ことを意味します。
したがって、このAwkコマンドが正常に終了する唯一の方法は、10行目に達する前にファイルの終わりに達した場合です。
したがって、Awkスクリプトが正常に終了した場合、10行未満のファイルがあることを意味します。
次の-exec呼び出し(を削除した場合echo)は、次findのコマンドを実行して、各ファイルを削除します(これは、のプライマリの評価でこれまでに取得したものです)。
rm -f ./somefilename
述語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幸せなら削除します。
これは、すべてのファイルのすべての行を数えるという点では特に効率的ではありませんが、1行x目で停止するだけで、各ファイルに対してwc1 つ(場合によっては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てください。
shは$0、たとえば、エラーメッセージに使用するために、そのインラインスクリプトのに入るものです。wc -l "$file"ここでは不要なファイル名が出力されwc、ファイルを開くことができない場合でも実行されます。()に$xエクスポートされ、それ自体がに渡します。findx=10 find...sh
find: -readable: unknown primary or operator。
bash。bash単なるコマンドラインインタープリターですが、find実装の一部です。-readableGNU拡張機能であり、OS / Xでは使用できませんfind。読み取り可能なファイルに限定するためにのみ使用されます(読み取り不可能なファイルの行数を取得することはできません)。最初の1つは省略できwcます。読み取り不可能なファイルのファイルを開くと、エラーメッセージが表示されます。
shは何ですか?2.wc -l < "$file"より速いですwc -l "$file"か?3. sh$xは、呼び出し側のBashシェルで定義されているの値をどのようにして知るのですか?