计算所有不可删除文件的总大小(包括子目录中的文件)
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
,看看它是否按预期工作?以上是关于计算所有不可删除文件的总大小(包括子目录中的文件)的主要内容,如果未能解决你的问题,请参考以下文章