사용자별로 그룹화하여 파일을 반복적으로 나열하고 크기를 합산합니다.

사용자별로 그룹화하여 파일을 반복적으로 나열하고 크기를 합산합니다.

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

각 사용자가 소유한 파일이 차지하는 드라이브 공간을 계산합니다.

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 명령은 단순히 특정 사용자에 대한 모든 파일의 모든 크기를 요약합니다. 모든 파일이 처리되면 모든 사용자의 전체 목록과 해당 사용자에 대한 모든 파일의 전체 크기가 인쇄됩니다.

관련 정보