人間が読めるサイズをソートする方法


11

私は基本的にファイルを探して、サイズでソートしています。人間が読めるサイズでサイズをソートしなければ、スクリプトは機能します。しかし、サイズは人間が読めるサイズにしたいです。人間が読めるサイズをソートするにはどうすればよいですか?

例えば:

 ls -l | sort -k 5 -n | awk '{print $9 " " $5}'

これは期待どおりに機能し、ファイルのサイズはバイト単位で昇順になりました:

1.txt 1
test.txt 3
bash.sh* 573
DocGeneration.txt 1131
andres_stuff.txt 1465
Branches.xlsx 15087
foo 23735
bar 60566
2016_stuff.pdf 996850

さて、サイズを人間が読めるようにしたいので、lsに-hパラメーターを追加しましたが、いくつかのファイルが故障しています:

 ls -lh | sort -k 5 -n | awk '{print $9 " " $5}'
1.txt 1
DocGeneration.txt 1.2K
andres_stuff.txt 1.5K
test.txt 3
Branches.xlsx 15K
foo 24K
bar 60K
bash.sh* 573
2016_stuff.pdf 974K


-k 5—それはどのように機能しますか?
ctrl-alt-delor

@ ctrl-alt-delor:サイズはls出力の5列目にあると
思い

2
du代わりに使用lsすることをお勧めします。
ゼノイド

...またはfind「S -printfそのと%pし、%sフォーマッタ(サイズの『ヒト化』が続きます)。
スティーブンキット

@Jesse_b私のエラー、質問のデータ(これは私が得たものであるとマークされている)がソートされた入力であると仮定しただけです。
ctrl-alt-delor

回答:


28

試してみる sort -h k2

-h、-human-numeric-sortは、人間が読み取れる数字を比較します(例:2K 1G)

これは、gnuソート、BSDソートなどの一部です。


5
出力の解析をls避けるべきではありませんか?

3
@Tomaszいつもではありません。必要な出力を提供する場合、別のフォーマット操作にパイプすることは特に危険ではありません。すべきではないのは、の出力をループし、ls代わりにファイルグロビングを直接使用することです。ここではグローブだけでは機能しません。とはいえ、私はおそらくこれを好むでしょうdu
ブラッドゲイン

1
ls形式の@Bloodgainは、システム/ lsバイナリ間で同じであることが保証されていないため、移植性のある構文解析は不可能と見なされます。
D.ベンノーブル

1
また、空白文字を含むファイル名は、物事をマングルします
D.ベンKnoble

1
@Bloodgain:(files=(); for f in *; do [[ -L "$f" ]] && files+=("$f"); done; echo ${#files[@]}シンボリックリンクテストスイッチが間違っている可能性があります)。シンボリックリンクを気にしない場合、配列ではなくfiles=(*); echo ${#files[@]}使用するsetと移植可能になります。
D.ベンKnoble

29

lsこの機能が組み込まれている場合、-Sオプションを使用し、逆の順序で並べ替えます。ls -lShr

       -r, --reverse
              reverse order while sorting

       -S     sort by file size, largest first

1
-h標準lsオプションではありませんが、OPに既にある場合は使用可能でなければなりません。残りは標準であり、それは確かに私が書いていた答えです。
トビースパイト

5
+1の出力の解析を混乱させないでくださいls
デヴィッドリチャービー

これが最良の答えですが、@ Tobyのコメントに情報を含める必要-Sがありますls。FWIW -Sls-lisp.el、OSにが存在しないときに使用されるEmacsのライブラリでもサポートされlsます。たとえば、MS Windows上のEmacsで動作します。
ドリュー

これは受け入れられた答えであるはずです。
スキャター

1
@Drew:Tobyのコメントは、-h普遍的に入手可能ではないかもしれないと言っていますが、OPはとにかくそれをすでに使用しています。これは、Tobyが提供するPOSIXリンク内にあるため、-S実際に普遍的に利用できるはずです。ただし、非常に多くの非POSIXツールキットが存在します。
ケビン

5

特定のシェルについては言及されていないため、zshシェルですべてを実行する方法を次に示します。

ls -lhf **/*(.Lk-1024oL)

**以下のようなグロブパターンが一致した*が、全体で/のように、すなわち、パス名に再帰的な検索が行うだろう。

このlsコマンドは、で人間が読み取り可能なサイズを有効にし-h、で長いリスト出力形式を有効にし-lます。この-fオプションは並べ替えを無効lsにするため、指定された順序でファイルをリストします。

この順序は、**/*(.Lk-1024oL)ファイル名のグロビングパターンによって配列されているため、小さいファイルが最初にリストされます。この**/*ビットは、このディレクトリ以下のすべてのファイルとディレクトリに一致しますが(...)、グロブの動作を変更します(「グロブ修飾子」です)。

それはだoL最後にその注文(oファイルサイズによって)名称(L「長さ」)。

.開始時には、グロブのみを通常のファイル(なしのディレクトリ)と一致します。

Lk-1024サイズが1024未満KB(「1024未満KBの長さ」)であるビットを選択するファイル。

zshがプライマリインタラクティブシェルでない場合は、使用できます

zsh -c 'ls -lf **/*(.Lk-1024oL)'

setopt GLOB_DOTS(またはzsh -o GLOB_DOTS -c ...)を使用して、非表示の名前も一致させます。...または単にDglob修飾子文字列に追加します。


上記を拡張し、パス名と人間が読めるサイズの2列の出力が必要だと仮定しnumfmt、GNU coreutilsからのものであると仮定して、

zmodload -F zsh/stat b:zstat

for pathname in **/*(.Lk-1024oL); do
    printf '%s\t%s\n' "$pathname" "$(zstat +size "$pathname" | numfmt --to=iec)"
done

または、より迅速に、

paste <( printf '%s\n' **/*(.Lk-1024oL) ) \
      <( zstat -N +size **/*(.Lk-1024oL) | numfmt --to=iec )

4

オプションsortがない場合は-h、次のような(非常に長い)awkコマンドを使用できます。

find . -type f -size -1024k -exec ls -al {} \; | sort -k 5 -n | awk '{if ($5 > 1099511627776) {print $9,$5/1024/1024/1024/1024"T"} else if ($5 > 1073741824) {print $9,$5/1024/1024/1024"G"} else if ($5 > 1048576) {print $9,$5/1024/1024"M"} else if ($5 > 1024) {print $9,$5/1024"K"} else {print $9,$5"B"}}' | column -t

これにより、出力がバイト単位でソートされ、その後人間が読めるサイズに変換されます。


-1

これは機能しますか?

ls -l | awk '{if ($5<=1024) {print}}' | sort -k 5 -n | awk '{print $9"\t"substr($5/1024,1,3)"k"} '| column -t

最初のawkexpは1M未満のファイルを検索し、2番目のexpは結果からバイトサイズを取得してKBに変換し、最初の3つの要素を印刷して人間が読めるサイズにします。


これは、OPの問題を実際に解決するものではありません。現在のディレクトリのみを検索し、通常のファイルのみを印刷します。また、1MBではなく1Kbと比較します。最後に、なぜコードが機能するのかについての説明がいくつかあります。
-grochmal

私の悪いはそれが何をするかを追加しました。
Vignesh SP
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.