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番目のフィールド)で索引付けされた連想配列を更新する場所に提供されます。$2
seen
では、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
所有者を探すfor
find
コマンドラインを使用して、各所有者に属するすべてのファイルを繰り返します。- ファイル名を次にパイプします。
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コマンドは、単に特定のユーザーのすべてのファイルのすべてのサイズを要約します。すべてのファイルが処理されると、すべてのユーザーの完全なリストとそのユーザーのすべてのファイルの合計サイズが印刷されます。