シェルスクリプトのコマンドヘッダに出力エラーがあります。

シェルスクリプトのコマンドヘッダに出力エラーがあります。

head コマンドでエラーが発生しました。ディレクトリには2つの48バイトファイルがあり、ディレクトリパスと一緒に2回印刷されるのではなく1回だけ印刷されます。 headコマンドが最初の2つのファイルを考慮しないのはなぜですかhead -n 2?別の方法がありますか?

私のコード:

find "$dir" -type f -printf '%s %p\n' | sort -n -r | head -n 2|
             {
              read -r file dir
              printf "size: %d\n\t%s\n" "$file" "$dir"
              }

私の出力エラー:

size: 48
      testdir/file7.txt

testdir ディレクトリには同じサイズの 48 の 2 つのファイルが含まれていますが、ディレクトリパスと一緒に 2 回ではなく 1 回だけ発生します。

私が望む出力:

size: 48
      testdir/file7.txt
      testdir/file1.txt

答え1

head -n 2;エラーはありません。|コードを削除して従うと、それを確認できます。

問題は、中かっこの間のコードが一度だけ実行されることです。これはループではありません。read1行の入力からのみデータを読み取ります。したがって、複数のファイルからデータを印刷するには、一種のループを実行する必要があります。

ループを使用するwhileか、awkの組み込みループを利用してデータを読み取って印刷できます。たとえば、次のawkコマンドは、現在のファイルのサイズが古いファイルのサイズと異なる場合は、サイズ情報のみを印刷します。

awk 'BEGIN{size=-1}; {if($1!=size){size=$1; printf "size: %d\n", size}; printf "\t%s\n", $2}'

私たちはしません本物自動的に空の文字列に初期化されるため、明示的な初期化が必要ですsizeが、IMHOこれらのことを明確にすることをお勧めします。


awk コマンドは以下を置き換えます。

{
    read -r file dir
    printf "size: %d\n\t%s\n" "$file" "$dir"
}

コードセクション。つまり、次のものを使用できます。

find "$dir" -type f -printf '%s %p\n' |
sort -n -r | head -n 2 |
awk 'BEGIN{size=-1}; 
{if($1!=size){size=$1; printf "size: %d\n", size}; 
printf "\t%s\n", $2}'

1行にすべて入れたり、複数行に分けることもできます。 awkプログラムを独自のファイルに入れることも可能ですが、そのような小さなプログラムには必要ありません。

-n必要なサイズを選択できhead、awkプログラムは期待どおりに実行されます。また、awkは非常にread高速 - を使用するよりも効率的ですprintf

FWIW、単純なテキスト処理のためのawkコードは、多くの場合、同等のPythonコードよりもはるかに高速なので、多くの人がawkを役に立たないと思いますが、それでもかなり人気があります。


データ印刷ただディレクトリで最大のファイルは次のとおりです。

find . -type f -printf '%s %p\n' | 
sort -nr | 
awk 'NR==1{size=$1;printf "size: %d\n", size};
$1!=size{exit};
{printf "\t%s\n", $2}'

これは、レコード数が1の場合にのみNR==1次のブロック(in)が実行されることを意味します。レコードは1行だけです。{}したがって、(前のコマンドのおかげで)最大のファイルである最初のファイルのサイズを取得し、変数に保存して sortサイズを印刷します。size

$1!=size{exit}最初のフィールドのデータが、変数に保存したデータと一致しない行を読み取るとすぐにプログラムを終了することを意味しますsize

最後のブロックは {printf "\t%s\n", $2}各ファイルのパス名を出力します。


findこのコマンドで見つけた最大のファイルと最小のファイルを印刷する方法はいくつかあります。 1つの方法は、すべてのデータをawkとして読み取って配列に保存し、配列をソートしてから、最大ファイルと最小サイズのファイルのデータを印刷することです。しかし、ここではより簡単な戦略を採用し、既存のコードをリサイクルします。これをより効率的にするために、awkプログラムをファイルに入れました。このファイルをコマンドパスのディレクトリに保存し、実行権限を付与します。

field1match.awk

#!/usr/bin/awk -f

# print only the records whose 1st field matches that of the 1st record
# Written by PM 2Ring 2015.05.21

NR==1{size=$1; printf "size: %d\n", size}
$1!=size{exit}
{printf "\t%s\n", $2}

tee以下は、出力をコピーfindしてソートし、プロセス置換を使用して印刷するコマンドラインです。

find "$dir" -type f -printf '%s %p\n' | 
tee > >(sort -n | field1match.awk) >(sort -rn | field1match.awk)

関連情報