Medir el espacio en disco de ciertos tipos de archivos en conjunto
Pregunta
Tengo algunos archivos en varias carpetas:
/home/d/folder1/a.txt
/home/d/folder1/b.txt
/home/d/folder1/c.mov
/home/d/folder2/a.txt
/home/d/folder2/d.mov
/home/d/folder2/folder3/f.txt
¿Cómo puedo medir la cantidad total de espacio en disco ocupado por todos los archivos .txt en /home/d/?
Sé du me dará el espacio total de una carpeta determinada, y ls -l me dará el espacio total de archivos individuales, pero ¿qué pasa si quiero sumar todos los archivos de texto y simplemente mirar el espacio ocupado por todos los archivos .txt en un total gigante ¿para todos los .txt en /home/d/ incluidas la carpeta1 y la carpeta2 y sus subcarpetas como la carpeta3?
Solución
Esto hará que:
total=0
for file in *.txt
do
space=$(ls -l "$file" | awk '{print $5}')
let total+=space
done
echo $total
Otros consejos
find folder1 folder2 -iname '*.txt' -print0 | du --files0-from - -c -s | tail -1
Esto reportar el uso de espacio en disco en bytes por extensión:
find . -type f -printf "%f %s\n" |
awk '{
PARTSCOUNT=split( $1, FILEPARTS, "." );
EXTENSION=PARTSCOUNT == 1 ? "NULL" : FILEPARTS[PARTSCOUNT];
FILETYPE_MAP[EXTENSION]+=$2
}
END {
for( FILETYPE in FILETYPE_MAP ) {
print FILETYPE_MAP[FILETYPE], FILETYPE;
}
}' | sort -n
Salida:
3250 png
30334451 mov
57725092729 m4a
69460813270 3gp
79456825676 mp3
131208301755 mp4
simple:
du -ch *.txt
Si lo que desea es el espacio total necesario para aparecer, a continuación:
du -ch *.txt | tail -1
Aquí hay una manera de hacerlo (en Linux, usando GNU coreutils du
y la sintaxis de Bash), evitando href="http://mywiki.wooledge.org/ParsingLs" mala práctica :
total=0
while read -r line
do
size=($line)
(( total+=size ))
done < <( find . -iname "*.txt" -exec du -b {} + )
echo "$total"
Si desea excluir el directorio actual, utilice -mindepth 2
con find
.
Otra versión que no requiere la sintaxis de Bash:
find . -iname "*.txt" -exec du -b {} + | awk '{total += $1} END {print total}'
Tenga en cuenta que éstos no funcionarán correctamente con los nombres de archivo que incluyen saltos de línea (pero los que tienen espacios funcionará).
macOS
- utilizar la herramienta y la
du
-I
parámetro para excluir todos los otros archivos
Linux
-X, --exclude-from=FILE
exclude files that match any pattern in FILE
--exclude=PATTERN
exclude files that match PATTERN
GNU encontrar,
find /home/d -type f -name "*.txt" -printf "%s\n" | awk '{s+=$0}END{print "total: "s" bytes"}'
Sobre la base de ennuikiller, este se encargará de espacios en los nombres. Que tenía que hacer esto y conseguir un poco de informe:
encontrar -type f -name "* .wav" | grep exportación | ./calc_space
#!/bin/bash
# calc_space
echo SPACE USED IN MEGABYTES
echo
total=0
while read FILE
do
du -m "$FILE"
space=$(du -m "$FILE"| awk '{print $1}')
let total+=space
done
echo $total
A un trazador de líneas para aquellos con herramientas GNU en bash:
for i in $(find . -type f | perl -ne 'print $1 if m/\.([^.\/]+)$/' | sort -u); do echo "$i"": ""$(du -hac **/*."$i" | tail -n1 | awk '{print $1;}')"; done | sort -h -k 2 -r
Debe tener activado extglob:
shopt -s extglob
Si desea archivos punto a trabajar, debe ejecutar
shopt -s dotglob
Resultado de muestra:
d: 3.0G
swp: 1.3G
mp4: 626M
txt: 263M
pdf: 238M
ogv: 115M
i: 76M
pkl: 65M
pptx: 56M
mat: 50M
png: 29M
eps: 25M
etc.
Me gusta usar encontrar en combinación con xargs:
find . -name "*.txt" -print0 |xargs -0 du -ch
Añadir la cola si sólo desea ver el total general
find . -name "*.txt" -print0 |xargs -0 du -ch | tail -n1
mi solución para obtener un tamaño total de todos los archivos de texto en un camino y subdirectorios dado (usando oneliner Perl)
find /path -iname '*.txt' | perl -lane '$sum += -s $_; END {print $sum}'
Para cualquiera que desee hacer esto con MacOS en la línea de comandos, se necesita una variación basada en el argumento -print0 en lugar de printf. Algunas de las respuestas anteriores que abordan pero esto va a hacer de manera integral por extensión:
find . -type f -print0 | xargs -0 stat -f "%N %i" |
awk '{
PARTSCOUNT=split( $1, FILEPARTS, "." );
EXTENSION=PARTSCOUNT == 1 ? "NULL" : FILEPARTS[PARTSCOUNT];
FILETYPE_MAP[EXTENSION]+=$2
}
END {
for( FILETYPE in FILETYPE_MAP ) {
print FILETYPE_MAP[FILETYPE], FILETYPE;
}
}' | sort -n
Hay varios problemas potenciales con la respuesta aceptada:
- no desciende a subdirectorios (sin depender de funciones de shell no estándar como
globstar
) - En general, como lo señala Dennis Williamson a continuación, debe evitar analizando la salida de
ls
- es decir, si el usuario o grupo (columnas 3 y 4) tienen espacios, la columna 5 no tendrá el tamaño del archivo
- si tienes un millón de archivos de este tipo, esto generará dos millones de subcapas, y será lento
Como propuesto por Ghostdog74, puedes usar el específico de GNU -printf
opción de find
para lograr una solución más robusta, evitando todas las tuberías excesivas, subcapas, Perl y cosas raras. du
opciones:
# the '%s' format string means "the file's size"
find . -name "*.txt" -printf "%s\n" \
| awk '{sum += $1} END{print sum " bytes"}'
Sí, sí, soluciones usando. paste
o bc
También son posibles, pero no más sencillos.
En macOS, necesitarás usar Homebrew o MacPorts para instalar findutils
, y llama gfind
en cambio.(I ver la etiqueta "linux" en esta pregunta, pero también está etiquetada como "unix").
Sin GNU find
, aún puedes recurrir al uso du
:
find . -name "*.txt" -exec du -k + \
| awk '{kbytes+=$1} END{print kbytes " Kbytes"}'
…pero hay que tener en cuenta el hecho de que du
La salida predeterminada está en bloques de 512 bytes por razones históricas (ver la sección "JUSTIFICACIÓN" aquí), y algunas versiones de du
(en particular, macOS) ni siquiera tener una opción para imprimir tamaños en bytes.
Muchas otras buenas soluciones aquí (ver La respuesta del granero. en particular), pero la mayoría sufre el inconveniente de ser innecesariamente compleja o depender demasiado de características exclusivas de GNU... ¡y tal vez en su entorno, eso esté bien!