Listar archivos de forma recursiva, agruparlos por usuario y sumar su tamaño

Listar archivos de forma recursiva, agruparlos por usuario y sumar su tamaño

Necesito verificar el tamaño que ocupa cada usuario en mi servidor Linux (todos los archivos de forma recursiva dentro de mi carpeta de datos).

Con el siguiente código puedo obtener todos mis archivos y sus usuarios, pero no sé cómo agruparlos y sumarlos después de eso.

#> find . -type f -ls | sort -k5

¿Alguien tiene una idea para resolver este problema?

Respuesta1

Con 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}'

Eso informaría el uso del disco en bytes para cada usuario. Al igual que duesto, tiene cuidado de no contar los enlaces físicos varias veces.

findimprime el dispositivo+número de inodo ( %D+%i) para cada archivo (para enlaces físicos al mismo archivo, serían idénticos), el nombre de usuario y el uso del disco en unidades de 512 bytes.

:se utiliza como separador de campos, ya que los nombres de usuario normalmente no los contienen, ya que son el separador de campos en la base de datos del usuario (como /etc/passwdo la salida de getent passwd).

Esa lista se envía a awk, donde actualizamos una dumatriz asociativa indexada en el nombre del usuario ( $2el segundo campo) para cada uno de los archivos para los cuales el primer campo aún no ha sido seen.

En END, recorremos los elementos de la matriz asociativa para informar el uso acumulado del disco para cada usuario (multiplicando el número debloquespara obtener la información en bytes).

Respuesta2

Esto debería funcionar. Es un poco lento y utiliza todos los usuarios en su /etc/passwd, pero eso es fácil de cambiar y no estoy seguro de qué tipo de usuarios tiene ( lastlogsupongo que también funcionaría).

Tenga en cuenta que esto utiliza el directorio de trabajo actual (consulte el find .)

El oneliner:

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

Aquí es lo mismo, pero un poco más detallado:

# 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

Respuesta3

Calcular el espacio en disco ocupado por los archivos propiedad de cada usuario

Este bashshellscript utiliza

  • findpara encontrar a los dueños
  • un forbucle con una findlínea de comando para encontrar todos los archivos que pertenecen a cada propietario
    • y canalizar los nombres de los archivos adu
  • después de que duel resultado se procese posteriormente para que sea fácil de leer.

El shellscript es bastante rápido cuando se prueba en particiones con muchos archivos.

#!/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

Ejemplos de demostración

Asumiendo el nombredisk-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

Diálogo en un impulso vivo y persistente.

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

Los enlaces duros se cuentan solo una vez

$ 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    .

Respuesta4

Esto podría ser un poco más rápido si tienes las versiones correctas de find, stat y 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])}}'

Esto ejecutará el comando stat(1) en todos los archivos encontrados por el comando find(1). La estadística imprimirá el nombre de usuario y el tamaño del archivo. Luego esto pasará a awk. El comando awk simplemente resume todos los tamaños de todos los archivos de un usuario determinado. Una vez que se hayan procesado todos los archivos, imprimirá todos los usuarios que están en la lista de suma, junto con el tamaño total de todos los archivos de ese usuario.

información relacionada