我有一个递归遍历目录的脚本,并将运行ls -alh --block-size=KB | grep ^\-
的结果附加到文件中。然后,我需要通过减小文件大小来对结果文件进行排序,就像使用-S
选项一样,如果在调用ls
时使用它。
答案 0 :(得分:1)
Why you shouldn't parse the output of ls和Fixing Unix/Linux/POSIX Filenames很好地涵盖了尝试解析ls
的许多问题,以便了解其他人在您面前的尝试。
您的方法无法可靠运行的其他一些原因:
ls
的某些版本可能会添加一列来显示新的设备ID并抛弃你的排序和解析; sed
删除ls -h
输出的kB / mB / gB幅度。这将把2字节文件,2千字节文件和2兆字节文件排在一起,大小相同。 ls
的输出在您管道或在终端显示时也会发生变化,同时也会更改解析/排序的逻辑。 解决方案是使用glob并根据ls
输出的添加列进行排序。
我们可以使用dd
创建一些已知大小的测试文件列表:
dd if=/dev/zero of=A bs=2 count=1
dd if=/dev/zero of=B bs=1024 count=2
dd if=/dev/zero of=C bs=1024 count=3
dd if=/dev/zero of=D bs=1024 count=150
dd if=/dev/zero of=E bs=1024 count=2000
导致:
$ ls -lh *
-rw-r--r-- 1 andrew wheel 2B Jan 8 20:52 A
-rw-r--r-- 1 andrew wheel 2.0K Jan 8 20:52 B
-rw-r--r-- 1 andrew wheel 3.0K Jan 8 20:52 C
-rw-r--r-- 1 andrew wheel 150K Jan 8 20:52 D
-rw-r--r-- 1 andrew wheel 2.0M Jan 8 20:52 E
如果您按ls
开关对-S
的输出进行排序:
$ ls -lhS *
-rw-r--r-- 1 andrew wheel 2.0M Jan 8 20:52 E
-rw-r--r-- 1 andrew wheel 150K Jan 8 20:52 D
-rw-r--r-- 1 andrew wheel 3.0K Jan 8 20:52 C
-rw-r--r-- 1 andrew wheel 2.0K Jan 8 20:52 B
-rw-r--r-- 1 andrew wheel 2B Jan 8 20:52 A
您的方法会删除第五列中的M
K
或B
,然后对其进行排序。这将导致A,B和E一起排序。
(可能 粗略对ls
的输出进行排序,如下所示:
$ ls -al | grep ^\- | sort -nrk 5
-rw-r--r-- 1 andrew wheel 2048000 Jan 8 20:52 E
-rw-r--r-- 1 andrew wheel 153600 Jan 8 20:52 D
-rw-r--r-- 1 andrew wheel 3072 Jan 8 20:52 C
-rw-r--r-- 1 andrew wheel 2048 Jan 8 20:52 B
-rw-r--r-- 1 andrew wheel 2 Jan 8 20:52 A
但是这不会产生你拥有的-h
的输出......)
正确的方法是使用带有glob的Decorate / Sort / Undecorate pattern。
for fn in *; do
[ -f "$fn" ] || continue
c1=$(($(wc -c < "$fn")))
c2=$(ls -alh "$fn")
printf "%s\t%s\n" "$c1" "$c2"
done | sort -nrk 1 | cut -f 2
结果:
-rw-r--r-- 1 andrew wheel 2.0M Jan 8 20:52 E
-rw-r--r-- 1 andrew wheel 150K Jan 8 20:52 D
-rw-r--r-- 1 andrew wheel 3.0K Jan 8 20:52 C
-rw-r--r-- 1 andrew wheel 2.0K Jan 8 20:52 B
-rw-r--r-- 1 andrew wheel 2B Jan 8 20:52 A
与使用ls -lhS
如果要递归文件树并写入文件,则一般方法是相同的。
答案 1 :(得分:0)
我的解决方案对我的目的来说足够好,尽管接受的答案要好得多:
sed 's/kB//' files.tmp > files1.tmp #remove first instance of "kB" from each line
sed 's/ \+/ /g' files1.tmp > files2.tmp #replace all multiple spaces with single space
sort -k 5n,5 files2.tmp | tac > files3.tmp #sort by numeric file size and reverse
这仅适用于向--block-size=KB
提供ls
选项。