如何对人类可读的大小进行排序

tvo*_*000 13 ls find sort

我基本上是在寻找文件,然后按大小排序。如果我不按人类可读的大小对大小进行排序,则该脚本有效。但我希望大小是人类可读的。如何对人类可读的尺寸进行排序?

例如:

 ls -l | sort -k 5 -n | awk '{print $9 " " $5}'
Run Code Online (Sandbox Code Playgroud)

这按预期工作,我的文件大小以字节为单位递增:

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
Run Code Online (Sandbox Code Playgroud)

现在,我希望大小是人类可读的,所以我在 ls 中添加了一个 -h 参数,现在有些文件乱了:

 ls -lh | sort -k 5 -n | awk '{print $9 " " $5}'
Run Code Online (Sandbox Code Playgroud)
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

Run Code Online (Sandbox Code Playgroud)

ctr*_*lor 35

尝试 sort -h k2

-h, --human-numeric-sort 比较人类可读的数字(例如,2K 1G)

它是 gnu 排序、BSD 排序等的一部分。

  • 不应该避免解析 `ls` 的输出吗? (5认同)
  • @Tomasz 并非总是如此。如果它提供了您需要的输出,则将其通过管道传输到另一个格式化操作并不是特别危险。你不应该做的是*循环*`ls`的输出,而是直接使用文件globbing。光靠流口水在这里是行不通的。也就是说,我可能更喜欢“du”。 (3认同)

Mar*_*try 29

ls内置此功能,使用该-S选项并按相反顺序排序:ls -lShr

       -r, --reverse
              reverse order while sorting

       -S     sort by file size, largest first
Run Code Online (Sandbox Code Playgroud)

  • +1 不要乱解析`ls`的输出。 (5认同)

Kus*_*nda 5

由于没有提到特定的 shell,这里是如何在zshshell 中完成整个事情:

ls -lhf **/*(.Lk-1024oL)
Run Code Online (Sandbox Code Playgroud)

**glob模式匹配一样*,但对面/的路径名,即像一个递归搜索会做。

ls命令将启用人类可读的大小-h和长列表输出格式-l。该-f选项禁用排序,因此ls只会按照给定的顺序列出文件。

此顺序按**/*(.Lk-1024oL)文件名通配模式排列,以便首先列出较小的文件。该**/*位匹配此目录及以下目录中的每个文件和目录,但会(...)修改 glob 的行为(它是“glob 限定符”)。

这是oL在年底的订单(o)按文件大小的名字(L“长度”)。

.一开始让水珠只匹配常规文件(无目录)。

Lk-1024位选择大小小于 1024 KB(“长度以 KB 为单位小于 1024”)的文件。

如果zsh不是您的主要交互式 shell,那么您可以使用

zsh -c 'ls -lf **/*(.Lk-1024oL)'
Run Code Online (Sandbox Code Playgroud)

使用setopt GLOB_DOTS(或zsh -o GLOB_DOTS -c ...)也匹配隐藏名称。...或者只是添加D到 glob 限定符字符串。


扩展上述内容,假设您需要带有路径名和人类可读大小的 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
Run Code Online (Sandbox Code Playgroud)

或者,更快,

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