
我需要驗證 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 指令只是匯總給定使用者的所有檔案的所有大小。處理完所有文件後,它將列印出總清單中的所有用戶,以及該用戶的所有文件的總大小。