计算所有不可删除文件的总大小(包括子目录中的文件)

Posted

技术标签:

【中文标题】计算所有不可删除文件的总大小(包括子目录中的文件)【英文标题】:Calculate total size of all un-deletable files (including files in subdirectories) 【发布时间】:2021-11-08 06:21:46 【问题描述】:

我有一个有点奇怪的问题,服务器上有数百名用户的共享存储。我想确定我的用户无法删除的所有文件(如果我尝试运行自动删除脚本)。

对于所有这些已识别的文件,我需要长列表格式(即:完整路径、所有者、上次修改时间、大小)。我目前的理解是这将是我不可写直接父目录的所有文件,如果这种方法错误,请纠正我。

识别这些文件后,我还需要获取它们占用的总大小。虽然,这一步也可以通过使用简单的 python 脚本来完成,也可以添加所有的大小,但我仍在寻找是否有更好的方法。

这是我目前的做法:

find /downloads/ -type d ! -writable -print0 |
xargs -0 -I. find . -maxdepth 1 -type f -print0 |
xargs -0 -I. ls -l . > myfile.txt
查找所有我的用户不可写的目录(递归) 查找每个目录的所有直接子目录,并仅过滤掉文件。 获取每个已识别文件的长列表并将结果存储在 .txt 文件中 使用 python 读取这个 .txt 文件并添加所有单独的大小(以字节为单位)以获得总大小。除以 (1024*1024*1024) 得到以 GB 为单位的大小。 (下面的python脚本:)
with open("myfile.txt", "r") as f:
    total_size = 0
    for line in f:
        try:
            data = line.split()
            if len(data) > 5:
                total_size += int(data[4]) # "4" is the index of the size column
        except:
            pass
print("Total Size:", str(round(total_size/(1024*1024*1024), 2)), "GB")

我使用这种方法面临的问题是我得到的最终大小是整个卷的总大小。

我的答案 = 1400.02GB(按照上述步骤报告) 整个共享空间的总大小 = 1400.02GB 共享服务器上的实际占用空间 = 800GB 预期答案应为

所以你看到问题是我的答案等于整个服务器空间的总大小,包括甚至没有被占用的空间。


我的答案 (1400.02GB) 与预期答案 (

有人可以提出一个更好的方法来做到这一点,或者指出我的方法中的问题,以便我可以解决它。非常感谢。

【问题讨论】:

你的 find 行在我看来还不错。您是否仅在该远程共享上遇到该问题?您是否检查了 myfile.txt 中的(某些)行是否存在可疑匹配(计算行数也可以给出第一个想法)?您也可以发布您的 Python 脚本吗? 可以通过find . -type d -writable -print0 | xargs -0 -I. find . -maxdepth 1 -type f -print0 | du -csh --files0-from=- 获得总计 @HarshitJindal:我根本不会在这里使用ls。相反,我会将文件名输入 Python 并直接从 Python 中进行大小计算。我认为这将更容易发现任何差异。 @senatoresconscripti 我已经提供了python文件,谢谢:) @LMC 非常感谢,它成功了。我终于得到了一个 471GB 的答案,这是有道理的,因为它大约是总占用量的一半 【参考方案1】:

我不知道为什么你的命令给出了这样一个错误的数字,但是你可以试试另一个。

请注意,由于文件系统块、硬链接和稀疏文件等原因,“它们占用的总大小”可能与 ls 打印的大小总和有很大差异。所以我们使用du 而不是ls 来获取尺寸。

以下命令基本上是LMC's comment,但将ls 合并到同一个搜索中并使用-exec + 而不是xargs -I,这应该会大大加快命令速度,因为您只运行第二个find少数几次,而不是每个目录一次。

#! /bin/bash

longlist() 
  ls -l "$@" >> "$longlistfile"

filesonly() 
  find "$@" -maxdepth 1 -type f -exec bash -c 'longlist "$@"' .  + -print0

export -f longlist filesonly
export longlistfile=myfile.txt

rm -f "$longlistfile"
find . -type d \! -writable -exec bash -c 'filesonly "$@"' .  + |
du -ch --files0-from=- | tail -n1

【讨论】:

【参考方案2】:

以下是为什么仅仅添加 ls 报告的字节来计算磁盘使用量被认为是幼稚的两个原因:

    您在重复计算硬链接文件,即使硬链接只是一个目录条目,基本上不会占用额外的磁盘空间。 如果您想了解实际的磁盘使用情况(“获取它们占用的总大小”),您必须考虑块大小。例如。一个包含 1000 个 1 字节文件的目录比一个包含一个 1MB 文件的目录占用更多空间

因此,适合这项工作的工具是 du。但是为了让du 能够正确地完成他的工作而不是重复计算硬链接,您必须一次将所有文件都提供给它来检查。幸运的是,du 的 GNU 版本有 --files0-from 选项,例如你可以使用

find . -type d ! -writable -print0 |
du -ch -d 1 --files0-from=- |
tail -n 1

这也避免了xargs,因为-I 选项可能会非常慢,这意味着您正在为每个参数执行find 调用。

【讨论】:

您的命令和@LMC 的命令find . -type d -writable -print0 | xargs -0 -I. find . -maxdepth 1 -type f -print0 | du -csh --files0-from=- 之间存在10GB 的细微差别,尽管您的运行时间明显减少 -d N 确实从总数中排除子目录。它只是防止打印比 N 级别更深的子目录的单个大小(-d 0 相当于 -s/--summarize)。 ¶ 你只有 small 差异意味着你的不可写目录不包含任何大的子目录。 至少对于 GNU du,从总数中排除子目录的唯一选项是 --exclude=PATTERN-X/-exclude-from=FILE。但是对于像/1-unwriteable/2-writeable/3-unwriteable 这样的目录结构,这些对于这项任务来说是毫无用处的。 @HarshitJindal, @Socowi:是的,我不确定-d 1(或-d 0)是否做对了。也许您可以尝试-S/--separate-dirs 选项,该选项记录为for directories do not include size of subdirectories,看看它是否按预期工作?

以上是关于计算所有不可删除文件的总大小(包括子目录中的文件)的主要内容,如果未能解决你的问题,请参考以下文章

Linux怎样计算一个目录下一部分文件的总大小

目录中所有文件内容的总大小[关闭]

删除包含特定内容的目录中的所有文件,无需直接计算其大小

计算多个文件夹的文件夹大小[关闭]

计算C中嵌套目录中文件的块大小

linux下如何统计部分文件大小,有很多文件夹,还包含子文件件夹,统计出所有包含‘123’的文件的总大小