ユーザーごとにグループ化してファイルを繰り返しリストし、サイズを合計します。

ユーザーごとにグループ化してファイルを繰り返しリストし、サイズを合計します。

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各ファイルのデバイス+iノード番号(%D+%i)(同じファイルへのハードリンクの場合は同じ)、ユーザー名、およびディスク使用量(512バイト単位)を印刷します。

:通常、ユーザー名には、ユーザーデータベースにあるように、これらのフィールド区切り文字が含まれていないため、フィールド区切り文字として使用されます(たとえば、/etc/passwdまたは出力getent passwd)。

awkこのリストは、最初のフィールドがまだ存在しないファイルごとに、ユーザーdu名(2番目のフィールド)で索引付けされた連想配列を更新する場所に提供されます。$2seen

では、END連想配列の要素を繰り返して、各ユーザーの累積ディスク使用量(ユーザー数を掛けます)を報告します。彫刻情報をバイト単位で取得します。)

答え2

これはうまくいきます。少し遅く、/etc/passwdのすべてのユーザーを使用しますが、変更するのは簡単です。どのようなユーザーがいるのかよくわかりません(lastlogそれも大丈夫だと思います)

これは現在の作業ディレクトリを使用していることに注意してください(参照find .)。

1本のライン:

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シェルスクリプトは

  • find所有者を探す
  • forfindコマンドラインを使用して、各所有者に属するすべてのファイルを繰り返します。
    • ファイル名を次にパイプします。du
  • du結果を読みやすくするために後処理します。

多数のファイルを含むパーティションでテストする場合、シェルスクリプトは非常に高速です。

#!/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コマンドは、単に特定のユーザーのすべてのファイルのすべてのサイズを要約します。すべてのファイルが処理されると、すべてのユーザーの完全なリストとそのユーザーのすべてのファイルの合計サイズが印刷されます。

関連情報