bash:使“du”显示类似于“ncdu”的输出

Gab*_*les 4 disk-usage ncdu

ncdu在 Linux 上,以下是NCurses 磁盘使用工具的一些示例输出:

命令:

ncdu /boot
Run Code Online (Sandbox Code Playgroud)
ncdu 1.14.1 ~ Use the arrow keys to navigate, press ? for help 
--- /boot -----------------------------------------------------
  100.2 MiB [##########]  initrd.img-5.13.0-28-generic         
  100.2 MiB [######### ]  initrd.img-5.13.0-27-generic
   11.2 MiB [#         ]  vmlinuz-5.11.0-46-generic
    9.7 MiB [          ]  vmlinuz-5.13.0-28-generic
    9.7 MiB [          ]  vmlinuz-5.13.0-27-generic
    9.7 MiB [          ]  vmlinuz-5.13.0-25-generic
    8.0 MiB [          ] /grub
    5.7 MiB [          ]  System.map-5.13.0-28-generic
    5.7 MiB [          ]  System.map-5.13.0-27-generic
    5.7 MiB [          ]  System.map-5.13.0-25-generic
    5.6 MiB [          ]  System.map-5.11.0-46-generic
  252.0 KiB [          ]  config-5.13.0-28-generic
  252.0 KiB [          ]  config-5.13.0-27-generic
  252.0 KiB [          ]  config-5.13.0-25-generic
  252.0 KiB [          ]  config-5.11.0-46-generic
  184.0 KiB [          ]  memtest86+_multiboot.bin
  184.0 KiB [          ]  memtest86+.elf
  180.0 KiB [          ]  memtest86+.bin
!  16.0 KiB [          ] /lost+found
!   4.0 KiB [          ] /efi
@   0.0   B [          ]  initrd.img.old
@   0.0   B [          ]  initrd.img
@   0.0   B [          ]  vmlinuz.old
@   0.0   B [          ]  vmlinuz
Run Code Online (Sandbox Code Playgroud)

但是,它是一个人机交互程序,并且输出不可编写脚本。我想将其存储到一个变量中,那么如何才能获得类似的输出呢du

这是我的问题的后续问题:如何ncdu显示磁盘使用情况的快速摘要并退出?

最终用途将如下所示:

ncdu 1.14.1 ~ Use the arrow keys to navigate, press ? for help 
--- /boot -----------------------------------------------------
  100.2 MiB [##########]  initrd.img-5.13.0-28-generic         
  100.2 MiB [######### ]  initrd.img-5.13.0-27-generic
   11.2 MiB [#         ]  vmlinuz-5.11.0-46-generic
    9.7 MiB [          ]  vmlinuz-5.13.0-28-generic
    9.7 MiB [          ]  vmlinuz-5.13.0-27-generic
    9.7 MiB [          ]  vmlinuz-5.13.0-25-generic
    8.0 MiB [          ] /grub
    5.7 MiB [          ]  System.map-5.13.0-28-generic
    5.7 MiB [          ]  System.map-5.13.0-27-generic
    5.7 MiB [          ]  System.map-5.13.0-25-generic
    5.6 MiB [          ]  System.map-5.11.0-46-generic
  252.0 KiB [          ]  config-5.13.0-28-generic
  252.0 KiB [          ]  config-5.13.0-27-generic
  252.0 KiB [          ]  config-5.13.0-25-generic
  252.0 KiB [          ]  config-5.11.0-46-generic
  184.0 KiB [          ]  memtest86+_multiboot.bin
  184.0 KiB [          ]  memtest86+.elf
  180.0 KiB [          ]  memtest86+.bin
!  16.0 KiB [          ] /lost+found
!   4.0 KiB [          ] /efi
@   0.0   B [          ]  initrd.img.old
@   0.0   B [          ]  initrd.img
@   0.0   B [          ]  vmlinuz.old
@   0.0   B [          ]  vmlinuz
Run Code Online (Sandbox Code Playgroud)

这是一个开始,但它没有按大小从最大到最小的正确降序显示输出:

output_before="$(du /boot)"
# do a bunch of stuff here which reduces the size of /boot
output_after="$(du /boot)"
echo "Before:"
echo "$output_before"
echo ""
echo "After:"
echo "$output_after"
Run Code Online (Sandbox Code Playgroud)

我最希望看到的是:

--- /boot -----------------------------------------------------
  100.2 MiB [##########]  initrd.img-5.13.0-28-generic         
  100.2 MiB [######### ]  initrd.img-5.13.0-27-generic
   11.2 MiB [#         ]  vmlinuz-5.11.0-46-generic
    9.7 MiB [          ]  vmlinuz-5.13.0-28-generic
    9.7 MiB [          ]  vmlinuz-5.13.0-27-generic
    9.7 MiB [          ]  vmlinuz-5.13.0-25-generic
    8.0 MiB [          ] /grub
    5.7 MiB [          ]  System.map-5.13.0-28-generic
    5.7 MiB [          ]  System.map-5.13.0-27-generic
    5.7 MiB [          ]  System.map-5.13.0-25-generic
    5.6 MiB [          ]  System.map-5.11.0-46-generic
  252.0 KiB [          ]  config-5.13.0-28-generic
  252.0 KiB [          ]  config-5.13.0-27-generic
  252.0 KiB [          ]  config-5.13.0-25-generic
  252.0 KiB [          ]  config-5.11.0-46-generic
  184.0 KiB [          ]  memtest86+_multiboot.bin
  184.0 KiB [          ]  memtest86+.elf
  180.0 KiB [          ]  memtest86+.bin
   16.0 KiB [          ] /lost+found
    4.0 KiB [          ] /efi
    0.0   B [          ]  initrd.img.old
    0.0   B [          ]  initrd.img
    0.0   B [          ]  vmlinuz.old
    0.0   B [          ]  vmlinuz
Run Code Online (Sandbox Code Playgroud)

但是,最低可接受的答案将如下所示:

  100.2 MiB  /boot/initrd.img-5.13.0-28-generic         
  100.2 MiB  /boot/initrd.img-5.13.0-27-generic
   11.2 MiB  /boot/vmlinuz-5.11.0-46-generic
    9.7 MiB  /boot/vmlinuz-5.13.0-28-generic
    9.7 MiB  /boot/vmlinuz-5.13.0-27-generic
    9.7 MiB  /boot/vmlinuz-5.13.0-25-generic
    8.0 MiB  /boot/grub
    5.7 MiB  /boot/System.map-5.13.0-28-generic
    5.7 MiB  /boot/System.map-5.13.0-27-generic
    5.7 MiB  /boot/System.map-5.13.0-25-generic
    5.6 MiB  /boot/System.map-5.11.0-46-generic
  252.0 KiB  /boot/config-5.13.0-28-generic
  252.0 KiB  /boot/config-5.13.0-27-generic
  252.0 KiB  /boot/config-5.13.0-25-generic
  252.0 KiB  /boot/config-5.11.0-46-generic
  184.0 KiB  /boot/memtest86+_multiboot.bin
  184.0 KiB  /boot/memtest86+.elf
  180.0 KiB  /boot/memtest86+.bin
   16.0 KiB  /boot/lost+found
    4.0 KiB  /boot/efi
    0.0   B  /boot/initrd.img.old
    0.0   B  /boot/initrd.img
    0.0   B  /boot/vmlinuz.old
    0.0   B  /boot/vmlinuz
Run Code Online (Sandbox Code Playgroud)

pLu*_*umo 7

python读取的小脚本ncdu -o-

read_ncdu.py:

#!/usr/bin/env python3

import sys, json

def sizeof_fmt(num, suffix='B'):
    for unit in ['','Ki','Mi','Gi','Ti','Pi','Ei','Zi']:
        if abs(num) < 1024.0:
            return "%3.1f%s%s" % (num, unit, suffix)
        num /= 1024.0
    return "%.1f%s%s" % (num, 'Yi', suffix)

def get_recursive(item):
    size = 0
    if isinstance(item, dict):
        name = item["name"]
        size = item["asize"]
    else:
        name = item[0]["name"]
        for sub in item:
            size += get_recursive(sub)[1]
    return (name, size)

data = json.loads(sys.stdin.read())

items=[]
for i in data[3][1:]:
    items.append(get_recursive(i))

sum_sizes = sum([item[1] for item in items])
biggest = max([item[1] for item in items])
print("------ {} --- {} -------".format(data[3][0]["name"], sizeof_fmt(sum_sizes)))

for item in sorted(items, key=lambda x:x[1], reverse=True):
    size=item[1]
    hsize=sizeof_fmt(item[1])
    name=item[0]
    percent=(size/sum_sizes*100)
    percent_str="({:.1f}%)".format(percent)
    
    print("{} {:8} [{}{}] {}".format(
        " " * (10 - len(str(hsize)))+ str(hsize),
        " " * (8 - len(percent_str)) + percent_str,  
        ('#' * round(size/biggest*10)),
        ('-' * round(10-size/biggest*10)),
        item[0])
    )
Run Code Online (Sandbox Code Playgroud)

您可能想改进脚本:

  • 如果您愿意,可以使用dsize(磁盘大小)代替asize(表观大小),或者向脚本引入参数以让用户决定。
  • os.walk()使用而不是使用输入使脚本独立ncdu -o-

另请参阅此处有关ncdujson 输出格式的说明。

跑步:

使read_ncdu.py可执行文件 --> chmod +x read_ncdu.py,然后你可以运行:

ncdu -o- /boot | ./read_ncdu.py
Run Code Online (Sandbox Code Playgroud)

输出:

------ /boot --- 224.3MiB -------
   56.8MiB  (25.3%)  [##########]  initrd.img-5.13.0-28-generic
   56.7MiB  (25.3%)  [##########]  initrd.img-5.13.0-27-generic
   55.4MiB  (24.7%)  [##########]  initrd.img-5.11.0-46-generic
   11.2MiB  (5.0%)   [##--------]  vmlinuz-5.11.0-46-generic
    9.7MiB  (4.3%)   [##--------]  vmlinuz-5.13.0-28-generic
    9.7MiB  (4.3%)   [##--------]  vmlinuz-5.13.0-27-generic
    6.5MiB  (2.9%)   [#---------]  grub
    5.7MiB  (2.5%)   [#---------]  System.map-5.13.0-28-generic
    5.7MiB  (2.5%)   [#---------]  System.map-5.13.0-27-generic
    5.6MiB  (2.5%)   [#---------]  System.map-5.11.0-46-generic
  251.7KiB  (0.1%)   [----------]  config-5.13.0-28-generic
  251.6KiB  (0.1%)   [----------]  config-5.13.0-27-generic
  248.1KiB  (0.1%)   [----------]  config-5.11.0-46-generic
  180.6KiB  (0.1%)   [----------]  memtest86+_multiboot.bin
  180.1KiB  (0.1%)   [----------]  memtest86+.elf
  178.4KiB  (0.1%)   [----------]  memtest86+.bin
   16.0KiB  (0.0%)   [----------]  lost+found
     28.0B  (0.0%)   [----------]  initrd.img
     28.0B  (0.0%)   [----------]  initrd.img.old
     25.0B  (0.0%)   [----------]  vmlinuz
     25.0B  (0.0%)   [----------]  vmlinuz.old
Run Code Online (Sandbox Code Playgroud)


Gab*_*les 6

这提供了每个问题的最低可接受答案:

\n
du --all --max-depth=1 -h /boot | sort -rh\n
Run Code Online (Sandbox Code Playgroud)\n

示例用法,根据问题中的示例(但制作为“一行”命令,以便我可以将其复制粘贴到终端中,而无需为其创建可执行文件脚本):

\n
output="$(du --all --max-depth=1 -h /boot | sort -rh)"; \\\necho "Before:"; \\\necho "$output"\n
Run Code Online (Sandbox Code Playgroud)\n

标准输出的示例输出:

\n
Before:\n273M    /boot\n101M    /boot/initrd.img-5.13.0-28-generic\n101M    /boot/initrd.img-5.13.0-27-generic\n12M /boot/vmlinuz-5.11.0-46-generic\n9.8M    /boot/vmlinuz-5.13.0-28-generic\n9.7M    /boot/vmlinuz-5.13.0-27-generic\n9.7M    /boot/vmlinuz-5.13.0-25-generic\n8.0M    /boot/grub\n5.7M    /boot/System.map-5.13.0-28-generic\n5.7M    /boot/System.map-5.13.0-27-generic\n5.7M    /boot/System.map-5.13.0-25-generic\n5.6M    /boot/System.map-5.11.0-46-generic\n252K    /boot/config-5.13.0-28-generic\n252K    /boot/config-5.13.0-27-generic\n252K    /boot/config-5.13.0-25-generic\n252K    /boot/config-5.11.0-46-generic\n184K    /boot/memtest86+_multiboot.bin\n184K    /boot/memtest86+.elf\n180K    /boot/memtest86+.bin\n16K /boot/lost+found\n4.0K    /boot/efi\n0   /boot/vmlinuz.old\n0   /boot/vmlinuz\n0   /boot/initrd.img.old\n0   /boot/initrd.img\n
Run Code Online (Sandbox Code Playgroud)\n

参考:

\n
    \n
  1. 感谢@terdon,他指出 sort -h可以按人类可读的大小进行排序,例如9.7 MiBvs 100 KiB
  2. \n
\n

也可以看看:

\n
    \n
  1. @Fabien Aur\xc3\xa9jac 指出的问答:服务器故障:如何按大小对 du -h 输出进行排序-sort -h可以对人类可读的输出进行排序du -h
  2. \n
\n