【问题标题】:Fastest ways to get a directory Size and Size on disk在磁盘上获取目录大小和大小的最快方法
【发布时间】:2011-09-23 19:20:56
【问题描述】:

我最近answered 提出了一个类似的问题,但我现在想做的是使用 bash 模拟 Windows“目录 --> 右键单击​​ --> 属性”功能(见图)。

我能够使用以下命令重现类似 Size: 的内容:

echo $(find . -type f -printf "%s+") | sed 's/+$//g' | bc

这是相当快的,但是否可以更快地获取信息(比查找)或更快地进行数学运算(比 bc)? 此外,我会使用 du -sb 命令来模拟 Size on Disk: 并可能使用另外一对 find 来计算文件和目录并模拟 Contains: 行.

有没有更好的方法来模拟这样的结果?

【问题讨论】:

    标签: windows linux bash


    【解决方案1】:

    假设 cygwin:

    cd /cygdrive/c
    
    printf "Size: %s", $( du --apparent-size -sh )
    printf "Size on disk: %s", $( du  -sh )
    find . -printf "%y\n" | awk '
      $1 == "d" {dirs++} 
      END {printf("Contains: %d files, %d folders\n", NR-dirs, dirs)}
    '
    

    【讨论】:

    • 非常喜欢使用findawk 来获取文件和目录计数(+1!),但我不确定--apparent-size 选项。这是Windows返回的吗?从 du 手册页我不确定这是否是我的意思:确切的目录大小。
    • 关于文件/目录计数:指向目录的符号链接?您会将它们视为文件(始终)。好吧,也许它们实际上是文件......
    【解决方案2】:

    我刚刚写了一个基于nftw(1)的又快又脏的实用程序。

    该实用程序基本上只是手册页示例,添加了一些统计信息。

    功能性

    我选择了

    • 停留在单个装载点内
    • 不要遵循符号链接(为了简单起见,因为它通常是你想要的)
    • 请注意,它仍然会计算符号链接本身的大小:)
    • 它显示了外观大小(文件的长度)以及磁盘上的大小(分配的块)。

    测试,速度

    我在我的盒子上测试了二进制文件 (/tmp/test):

    # clear page, dentry and attribute caches
    echo 3> /proc/sys/vm/drop_caches 
    time /tmp/test /
    

    输出

    Total size: 28433001733
    In 878794 files and 87047 directories (73318 symlinks and 0 inaccessible directories)
    Size on disk 59942192 * 512b = 30690402304
    
    real    0m2.066s
    user    0m0.140s
    sys 0m1.910s
    

    我没有与您的工具进行比较,但它看起来确实相当快。也许您可以获取源代码并构建自己的版本以获得最大速度?

    测试稀疏文件是否确实被正确报告:

    mkdir sparse
    dd bs=1M seek=1024 count=0 of=sparse/file.raw
    ls -l sparse/
    ./test sparse/
    

    输出:

    total 0
    -rw-r--r-- 1 sehe sehe 1073741824 2011-09-23 22:59 file.raw
    
    Total size: 1073741884
    In 1 files and 1 directories (0 symlinks and 0 inaccessible directories)
    Size on disk 0 * 512b = 0
    

    代码

    #define _XOPEN_SOURCE 500
    #include <ftw.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <stdint.h>
    
    static uintmax_t total        = 0ul;
    static uintmax_t files        = 0ul;
    static uintmax_t directories  = 0ul;
    static uintmax_t symlinks     = 0ul;
    static uintmax_t inaccessible = 0ul;
    static uintmax_t blocks512    = 0ul;
    
    static int
    display_info(const char *fpath, const struct stat *sb,
                 int tflag, struct FTW *ftwbuf)
    {
        switch(tflag)
        {
            case FTW_D:
            case FTW_DP:  directories++;  break;
            case FTW_NS:
            case FTW_SL:
            case FTW_SLN: symlinks++;     break;
            case FTW_DNR: inaccessible++; break;
            case FTW_F:   files++;        break;
        }
        total += sb->st_size;
        blocks512 += sb->st_blocks;
        return 0; /* To tell nftw() to continue */
    }
    
    int
    main(int argc, char *argv[])
    {
        int flags = FTW_DEPTH | FTW_MOUNT | FTW_PHYS;
    
        if (nftw((argc < 2) ? "." : argv[1], display_info, 20, flags) == -1)
        {
            perror("nftw");
            exit(EXIT_FAILURE);
        }
    
        printf("Total size: %7jd\n", total);
        printf("In %jd files and %jd directories (%jd symlinks and %jd inaccessible directories)\n", files, directories, symlinks, inaccessible);
        printf("Size on disk %jd * 512b = %jd\n", blocks512, blocks512<<9);
    
        exit(EXIT_SUCCESS);
    }
    

    编译...

    gcc test.c -o test
    

    【讨论】:

    • 如果您将静态全局计数器放在命名空间中并将它们标记为“thread_local”,那么您可以使用您的方法作为获取磁盘大小信息的线程安全方式。
    猜你喜欢
    • 2021-09-05
    • 1970-01-01
    • 1970-01-01
    • 2023-04-04
    • 2020-08-02
    • 2011-04-14
    • 2020-10-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多