
내 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
$2
seen
에서는 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 명령은 모든 파일에 대해 특정 사용자의 모든 크기를 합산합니다. 모든 파일이 처리되면 합계 목록에 있는 모든 사용자와 해당 사용자에 대한 모든 파일의 총 크기가 인쇄됩니다.