我基本上是在寻找文件,然后按大小排序。如果我不按人类可读的大小对大小进行排序,则该脚本有效。但我希望大小是人类可读的。如何对人类可读的尺寸进行排序?
例如:
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 排序等的一部分。
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)
由于没有提到特定的 shell,这里是如何在zsh
shell 中完成整个事情:
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)