按文件类型获取磁盘利用率?

按文件类型获取磁盘利用率?

有没有办法从命令行根据文件类型了解磁盘(或目录)的利用率?

我想我可以find+du根据一些已知的文件类型编写一个 bash 脚本,但如果已经存在一个可以解析这个问题的包,我宁愿不重新发明轮子。

答案1

我编写了这个实用程序,它应该可以非常快速地运行,这是我的主目录中默认运行的输出:

??? 3897697700  (717MiB)
.tgz    1550090721  (1478MiB)
.jpg    872736861   (832MiB)
.iso    804329472   (767MiB)
.pack   636183905   (606MiB)
.gch    528345920   (503MiB)
.d  384725346   (366MiB)
.i  354098997   (337MiB)
.sqlite 302110738   (288MiB)
.html   233729943   (222MiB)
.cs 209534627   (199MiB)
.dll    198655123   (189MiB)
.xml    192561101   (183MiB)
.pdf    184729508   (176MiB)
.deb    173972838   (165MiB)

请注意,文章篇幅过大???是由于许多 .hg 和 .git 源存储库没有扩展名。

代码默认打印贡献最大的前 15 种文件类型,尽管可以轻松扩展。

代码中有一个 TODO,用于libmagic获取实际的文件类型。

以下是代码:

#define _XOPEN_SOURCE 500
#include <ftw.h>
#include <cstdio>
#include <cstdlib>
#include <stdint.h>

#include <set>
#include <vector>
#include <algorithm>
#include <string>
#include <iostream>

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;

struct byfiletype {
    std::string filetype;
    mutable uintmax_t total; // non-key

    bool operator<(const byfiletype& other) const { return filetype<other.filetype; }
    static bool largest_first(const byfiletype& a, const byfiletype& b) { return a.total>b.total; }
};

typedef std::set<byfiletype> sizemap;
static sizemap per_filetype;

std::string get_filetype(std::string fname) // TODO use libmagic to do file type detection?
{
    size_t pos = fname.rfind("/");
    if (std::string::npos != pos) fname = fname.substr(pos+1);

    pos = fname.rfind(".");

    return (std::string::npos != pos)
        ? fname.substr(pos)
        : "???";
}

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++; 
                      byfiletype entry = { get_filetype(fpath), sb->st_size };
                      sizemap::iterator match = per_filetype.find(entry);

                      if (match != per_filetype.end()) 
                          match->total += sb->st_size;
                      else 
                          per_filetype.insert(entry);

                      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);

    size_t N = std::min(15ul, per_filetype.size());
    typedef std::vector<byfiletype> topN_t;
    topN_t topN(N);
    std::partial_sort_copy(
            per_filetype.begin(), per_filetype.end(),
            topN.begin(), topN.end(),
            byfiletype::largest_first);

    for (topN_t::const_iterator it=topN.begin(); it!=topN.end(); ++it)
    {
        std::cout << it->filetype << "\t" << it->total << "\t(" << ((it->total)>>20) << "MiB)" << std::endl;
    }

    exit(EXIT_SUCCESS);
}

相关内容