我的目标是测量 Linux 系统上每个文件的文件大小(以 MB 或 GB 为单位),递归记录文件名和文件大小,并将输出通过管道传输到制表符分隔的文本文件中。
对此合适的命令是什么?
人们可以尝试这样的命令:
ls -lhR > outputfile.txt
但我有理由认为这是非常低效的:
http://mywiki.wooledge.org/ParsingLs
使用for循环会更合适吗?
答案1
sudo du -h / 2>/dev/null > out.csv
- 用于
sudo
确保您读取所有文件。 -h
与使用du
表示“H人类可读的”大小格式。- 不显示错误(
2>/dev/null
,其中2
是标准错误) - 将结果发送到文件 (
> out.csv
)。
这会生成一个包含文件大小和路径的列表,值之间有一个制表符。
答案2
试试这个(假设 GNUfind
并且文件名不包含双引号字符):
{
printf '%s\t%s\n' size path
find / \( -path /proc -o -path /sys \) -prune -o -printf '%s\t"%P"\n' |
numfmt --to=iec
} > outputfile.csv
查看
man find | less +/'-printf format'
或者
info --ind=-printf find
答案3
注意:下面的命令比您要求的稍多一些,但可能对其他人非常有用。
这是我与同事一起制定的命令,并提供给需要处理完整磁盘的应用程序支持团队:
find / -xdev \! -path /var/log/lastlog -printf '%s\t%p\n' | sort -rn | head | cut -f2- | xargs -n1 ls -lh | awk '{print $5, $NF}'
以下是带有换行符的相同命令,以便于阅读:
find / -xdev \! -path /var/log/lastlog -printf '%s\t%p\n' |
sort -rn | head | cut -f2- |
xargs -n1 ls -lh | awk '{print $5, $NF}'
此命令打印根文件系统上 10 个最大的文件,以及每个文件的人类可读文件大小。
需要运行该命令作为根用户以获得准确的结果。
-xdev
避免遍历文件系统边界,如果 NFS 可能很慢,这一点就很重要。
/var/log/lastlog
被忽略,因为它是一个稀疏文件,错误地报告了巨大的大小(即它不会导致磁盘已满问题)。
-printf
特定于 GNU 查找。在这种情况下,它会打印文件大小(以字节为单位),后跟文件的完整路径。
实际上,您可以在命令之后保留所有内容head
,唯一会丢失的是人类可读的文件大小。
所以下面的方法就可以了:
find / -xdev \! -path /var/log/lastlog -printf '%s\t%p\n' | sort -rn | head
这个命令才不是如果您的文件名中包含换行符,则可以使用。但由于该命令旨在供操作员手动处理(不在脚本中使用),因此这并不重要。
现在,回答您的特定问题:
我的目标是测量 Linux 系统上每个文件的文件大小(以 MB 或 GB 为单位),递归记录文件名和文件大小,并将输出通过管道传输到制表符分隔的文本文件中。
我将忽略 MB 或 GB 要求,只报告以字节为单位的文件大小,因为这非常非常容易做到。如果您确实需要,请参阅上面的命令以了解如何执行此操作。
sudo find / -printf '%s\t%p\n' > outputfile.txt
答案4
使用 GNUstat
和bash
globstar
:
shopt -s globstar
stat --printf="%s\t%n\n" -- ** | numfmt -d $'\t' --to=iec >out.csv
这确实包括目录,但是它们也是文件......
正如 @Patrick 指出的,这可能会导致argument list too long
由于**
.人们可以使用find
:
sudo find / -type f -exec stat --printf="%s\t%n\n" -- {} \; | numfmt -d $'\t' --to=iec