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

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

내 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주인을 찾기 위해
  • 각 소유자에게 속한 모든 파일을 찾는 명령줄이 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) 명령이 실행됩니다. 통계는 사용자 이름과 파일 크기를 인쇄합니다. 그런 다음 awk로 전달됩니다. awk 명령은 모든 파일에 대해 특정 사용자의 모든 크기를 합산합니다. 모든 파일이 처리되면 합계 목록에 있는 모든 사용자와 해당 사용자에 대한 모든 파일의 총 크기가 인쇄됩니다.

관련 정보