我需要验证 Linux 服务器上每个用户占用的大小(所有文件在我的数据文件夹中递归)。
使用下面的代码,我可以获得所有文件及其用户,但我不知道之后如何对它们进行分组和求和。
#> find . -type f -ls | sort -k5
有人有解决这个问题的想法吗?
答案1
使用 GNU find
:
find . -printf '%D+%i:%u:%b\n' | awk -F: '
!seen[$1]++ {du[$2] += $3}
END {for (user in du) printf "%20s: %lu\n", user, du[user] * 512}'
这将报告每个用户的磁盘使用情况(以字节为单位)。与du
此类似,请注意不要对硬链接进行多次计数。
find
打印每个文件的设备+inode 号 ( %D+%i
)(对于同一文件的硬链接,它们将是相同的)、用户名和磁盘使用情况(以 512 字节为单位)。
:
用作字段分隔符,因为用户名通常不包含这些字段分隔符,因为它们是用户数据库中的字段分隔符(如/etc/passwd
或 的输出getent passwd
)。
该列表被馈送到awk
,我们在其中为第一个字段尚未存在的每个文件更新du
以用户名(第二个字段)为索引的关联数组。$2
seen
在 处END
,我们循环关联数组的元素来报告每个用户的累积磁盘使用情况(乘以用户的数量)块获取以字节为单位的信息)。
答案2
这应该有效。它有点慢,它使用 /etc/passwd 中的所有用户,但这很容易更改,我不确定你拥有什么样的用户(lastlog
我猜也可以)
请注意,这使用当前工作目录(请参阅find .
)
单线:
for user in $(cut -d: -f1 < /etc/passwd); do echo -en "$user has:\t"; find . -user $user -type f -print0 | du --files0-from=- --total -sh | tail -n1 ; done
这是相同的,但更详细一些:
# Read all lines in /etc/password, use ":" as field separator and print first field
for user in $(cut -d: -f1 < /etc/passwd); do
# Print username, -e to allow \t, -n to skip newline
echo -en "$user is using:\t"
# Find all files owned by $user, print found files to stdout and terminate
# with a null character (thus circumventing the long file list problem).
# let `du` read from null terminated stdin usint --files0-from=-, make a total,
# make a summary and make it human readable, then only print the last line
# containing the total
find . -user "$user" -type f -print0 | du --files0-from=- --total -sh | tail -n1
done
答案3
计算每个用户拥有的文件占用的驱动器空间
这个bash
shell脚本使用
find
寻找业主for
使用命令行循环查找find
属于每个所有者的所有文件- 并将文件名通过管道传输到
du
- 并将文件名通过管道传输到
- 对结果进行后
du
处理以使结果易于阅读。
在包含大量文件的分区中进行测试时,shell 脚本相当快。
#!/bin/bash
# store owners in variable
user=$(whoami)
if [ "$user" != "root" ]
then
echo "Run with elevated permissions (as root or with sudo)"
exit
elif ! test -d "$1"
then
echo "Enter a target directory as parameter"
exit
fi
owners=$(find "$1" -printf "%u\n"|sort | uniq)
#echo "$owners"
leng=0
for i in $owners
do
if [ ${#i} -gt $leng ]
then
leng=${#i}
fi
done
#echo "$leng"
skip=$((leng - 4))
spc=$(for ((i=0;i<skip;i++)); do printf " "; done)
printf "User $spc Size\n---- $spc ----\n"
for i in $owners
do
skip=$((leng - ${#i}))
spc=$(for ((i=0;i<skip;i++)); do printf " "; done)
printf "$i $spc "
find "$1" -type f -user "$i" -print0 | du --files0-from=- --total -sh |
tail -n1 | cut -f 1
done
演示示例
假设名字disk-usage-by-owner
ubuntu@ubuntu:~$ ./disk-usage-by-owner
Run with elevated permissions (as root or with sudo)
ubuntu@ubuntu:~$ sudo ./disk-usage-by-owner
Enter a target directory as parameter
持续实时驾驶中的对话
ubuntu@ubuntu:~/bin$ sudo ./disk-usage-by-owner /cdrom
User Size
---- ----
root 1.9G
ubuntu@ubuntu:~/bin$ sudo ./disk-usage-by-owner /home
User Size
---- ----
root 0
ubuntu 1.9G
ubuntu@ubuntu:~/bin$ sudo ./disk-usage-by-owner /media/ubuntu/casper-rw
User Size
---- ----
_apt 0
colord 44K
gdm 288K
man 628K
root 1007M
syslog 127M
systemd-timesync 0
ubuntu 1.9G
硬链接仅计算一次
$ sudo find . -user root -ls
56492055 1024 -rw-r--r-- 3 root root 1048576 jan 16 23:41 ./owned\ by\ root\ hard-linked
56492055 1024 -rw-r--r-- 3 root root 1048576 jan 16 23:41 ./owned\ by\ root
56492055 1024 -rw-r--r-- 3 root root 1048576 jan 16 23:41 ./sub/owned\ by\ root
$ sudo ./disk-usage-by-owner .
User Size
---- ----
root 1,0M
sudodus 32K
$ du .
4 ./sub
1064 .
答案4
如果您有正确版本的 find、stat 和 awk,这可能会快一点:
find . -type f -exec stat -c "%U %s" {} \; | awk '{sum[$1]+=$2} END {for (u in sum) {printf("%s: %d\n", u, sum[u])}}'
这将对 find(1) 命令找到的所有文件运行 stat(1) 命令。 stat 将打印出用户名和文件大小。然后这将传递给 awk。 awk 命令只是汇总给定用户的所有文件的所有大小。处理完所有文件后,它将打印出总列表中的所有用户,以及该用户的所有文件的总大小。