我基本上是在寻找文件,然后按大小排序。如果我不按人类可读的大小对大小进行排序,该脚本就可以工作。但我希望尺寸是人类可读的。如何对人类可读的尺寸进行排序?
例如:
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
答案1
尝试sort -h k2
-h, -- human-numeric-sort 比较人类可读的数字(例如,2K 1G)
它是 gnu 排序、BSD 排序等的一部分。
答案2
ls
内置此功能,使用该-S
选项并按相反顺序排序:ls -lShr
-r, --reverse
reverse order while sorting
-S sort by file size, largest first
答案3
由于没有提到特定的 shell,因此以下是如何在zsh
shell 中完成整个操作:
ls -lhf **/*(.Lk-1024oL)
glob模式与路径名中的**
like *
but across相匹配/
,即像递归搜索一样。
该ls
命令将使用 启用人类可读的大小-h
,并使用 启用长列表输出格式-l
。该-f
选项禁用排序,因此ls
只会按照给定的顺序列出文件。
此顺序按文件名通配模式排列,**/*(.Lk-1024oL)
以便首先列出较小的文件。该**/*
位匹配此目录及以下目录中的每个文件和目录,但会(...)
修改 glob 的行为(它是“glob 限定符”)。
oL
最后的 ( ) 按文件大小( “长度”)o
对名称进行排序。L
开头的.
使 glob 仅匹配常规文件(无目录)。
该Lk-1024
位选择大小小于 1024 KB 的文件(“以 KB 为单位的长度小于 1024”)。
如果zsh
不是您的主要交互式 shell,那么您可以使用
zsh -c 'ls -lf **/*(.Lk-1024oL)'
使用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
或者,更快,
paste <( printf '%s\n' **/*(.Lk-1024oL) ) \
<( zstat -N +size **/*(.Lk-1024oL) | numfmt --to=iec )
答案4
这行得通吗?
ls -l | awk '{if ($5<=1024) {print}}' | sort -k 5 -n | awk '{print $9"\t"substr($5/1024,1,3)"k"} '| column -t
第一个awk
exp 将查找小于 1M 的文件,第二个 exp 将从结果中获取字节大小并将其转换为 KB 并打印前 3 个元素以给出人类可读的大小。