遞歸列出文件,按使用者分組並求和其大小

遞歸列出文件,按使用者分組並求和其大小

我需要驗證 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以使用者名稱(第二個欄位)為索引的關聯數組。$2seen

在 處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

計算每個使用者擁有的檔案所佔用的磁碟機空間

這個bashshell腳本使用

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

相關內容