¿Cómo puedo obtener el tamaño de un archivo en un script bash?

¿Cómo puedo obtener el tamaño de un archivo en un script bash?

¿Cómo asigno esto a una variable bash para poder usarla más tarde?

Comentarios

  • stackoverflow.com/questions/5920333/how-to-check-size-of-a-file LOL para la migración 🙂
  • Emparejar esto con pv y cat para un comando de copia que muestra el progreso y ETA 🙂
  • stat -c% s archivo. nombre
  • En caso de un problema XY (muy estrecho), esto es genial: si todo lo que necesita es probar que el archivo tiene un tamaño distinto de cero, bash tiene una expresión condicional -s, por lo que puede simplemente probar si un archivo tiene una longitud distinta de cero con if [ -s file ]; then echo "file has nonzero size" ; fi

Respuesta

Su mejor opción si está en un sistema GNU:

stat --printf="%s" file.any 

De man stat :

% s tamaño total, en bytes

En un script bash:

#!/bin/bash FILENAME=/home/heiko/dummy/packages.txt FILESIZE=$(stat -c%s "$FILENAME") echo "Size of $FILENAME = $FILESIZE bytes." 

NOTA: consulte

respuesta de @chbrown » sobre cómo usar stat en terminal en Mac OS X.

Comentarios

  • @ haunted85 stat es la forma más sencilla, asumiendo que ‘ estás usando Linux o Cygwin (stat no es ‘ t estándar). wc -c como sugerido por Eug é ne es portátil.
  • stat: illegal option -- c
  • stat --printf="%s" file.txt doesn ‘ t generar cualquier cosa en Debian Jessie …
  • En MacOS, esto funciona: stat -f%z myfile.tar
  • @woohoo Su mensaje sobrescribe la salida. man stat dice que –printf omite la nueva línea final. Utilice --format o -c para ver el resultado. Obtenga más información comparando stat --printf="%s" file.any | xxd - con stat -c "%s" file.any | xxd -

Respuesta

file_size_kb=`du -k "$filename" | cut -f1` 

El problema con el uso de stat es que es una extensión GNU (Linux). du -k y cut -f1 están especificados por POSIX y, por lo tanto, son portátiles para cualquier sistema Unix.

Solaris, por ejemplo, se envía con bash pero no con stat . Por lo tanto, esto no es del todo hipotético.

ls tiene un problema similar en el sentido de que no se especifica el formato exacto de la salida, por lo que no se puede analizar de forma portátil su salida . du -h también es una extensión GNU.

Cíñete a construcciones portátiles siempre que sea posible, y le facilitarás la vida a alguien en el futuro. Tal vez la tuya propia.

Comentarios

  • du no ‘ t proporciona tamaño del archivo, da una indicación de cuánto espacio usa el archivo, que es sutilmente diferente (generalmente el tamaño informado por du es el tamaño del archivo redondeado al más cercano número de bloques, donde un bloque suele ser 512B o 1kB o 4kB).
  • @Gilles, los archivos dispersos (es decir, los que tienen agujeros) informan menos que la longitud.
  • Esto, con --bytes o -b en lugar de -k, debería ser la respuesta aceptada.
  • @fralau: El OP quiere » asignar esto a una variable bash para que puedan usarlo más tarde «, por lo que es mucho más probable que quieran un actu al valor numérico, no una aproximación legible por humanos. Además, -h es una extensión GNU; no es estándar
  • El uso de du con --apparent-size marca devolverá un más tamaño preciso (como se indica en man: print apparent sizes, rather than disk usage; although the apparent size is usually smaller, it may be larger due to holes in ('sparse') files, internal fragmentation, indirect blocks, and the like)

Respuesta

También puede utilizar el comando» recuento de palabras «(wc):

wc -c "$filename" | awk "{print $1}" 

El problema con wc es que «agregará el nombre del archivo y sangrará la salida. Por ejemplo:

$ wc -c somefile.txt 1160 somefile.txt 

Si desea evitar encadenar un lenguaje interpretado completo o un editor de flujo solo para obtener un recuento del tamaño del archivo, simplemente redirija la entrada del archivo para que wc nunca vea el nombre del archivo:

wc -c < "$filename" 

Esta última forma se puede usar con la sustitución de comandos para obtener fácilmente el valor que buscaba como una variable de shell, como lo menciona Gilles a continuación.

size="$(wc -c <"$filename")" 

Comentarios

  • wc -c <"$FILENAME" da el tamaño sin otro cruft, por lo que size=$(wc -c <"$FILENAME").
  • Solo un punto más: acabo de probarlo y wc -c < file parece ser muy rápido, al menos en OS X. I ‘ Supongo que wc tiene el cerebro para intentar establecer el archivo si solo se especifica -c.
  • @EdwardFalk: GNU wc -c usa fstat, pero luego busca el penúltimo bloque del archivo y lee el último hasta st_blksize bytes. Aparentemente esto se debe a que los archivos en Linux ‘ s /proc y /sys por ejemplo, tienen tamaños de estadísticas que son solo aproximados , y wc quiere informar el tamaño real, no el tamaño informado por estadísticas. Supongo que sería extraño que wc -c informe un tamaño diferente a wc, pero ‘ no es idea leer datos del archivo si es ‘ un archivo de disco normal, y ‘ no está en la memoria. O peor aún, almacenamiento en cinta near-line …
  • Parece que printf todavía ve la sangría, p. Ej. printf "Size: $size" – > size: <4 spaces> 54339. Por otro lado, echo ignora los espacios en blanco. ¿Alguna forma de hacerlo coherente?
  • @keithpjolley: llamando a fstat. Intente ejecutar strace wc -c </etc/passwd y podrá ver lo que está haciendo.

Responder

BSD «s (macOS» s) stat tiene un indicador de argumento de formato diferente y diferentes especificadores de campo. De man stat(1):

  • -f format: muestra información con el formato especificado. Consulte la sección FORMATOS para obtener una descripción de los formatos válidos.
  • … la sección FORMATOS …
  • z: el tamaño de archivo en bytes.

Así que todos juntos ahora:

stat -f%z myfile1.txt 

NOTA: consulte @ b01 «s answer sobre cómo usar el comando stat en sistemas GNU / Linux. 🙂

Comentarios

  • Tenga en cuenta que esta es una solución solo BSD. No ‘ no funciona con GNU stat, desafortunadamente.

Respuesta

Depende de lo que quieras decir con tamaño .

size=$(wc -c < "$file") 

le dará la cantidad de bytes que se pueden leer del archivo. IOW, es el tamaño del contenido del archivo. Sin embargo, leerá el contenido del archivo (excepto si el archivo es un archivo normal o un enlace simbólico a un archivo normal en la mayoría de las implementaciones de wc como optimización). Eso puede tener efectos secundarios. Por ejemplo, para una tubería con nombre, lo que se ha leído ya no se puede leer de nuevo y para cosas como /dev/zero o /dev/random que son de tamaño infinito, tomará un tiempo. Eso también significa que necesita read permiso para el archivo, y la marca de tiempo del último acceso del archivo puede ser actualizado.

Eso es estándar y portátil, sin embargo, tenga en cuenta que algunas wc implementaciones pueden incluir espacios en blanco a la izquierda en esa salida. Una forma de deshacerse de ellos es usar:

size=$(($(wc -c < "$file"))) 

o para evitar un error sobre una expresión aritmética vacía en dash o yash cuando wc no produce salida (como cuando el archivo «no se puede abrir):

size=$(($(wc -c < "$file") +0)) 

ksh93 tiene wc incorporado (siempre que lo habilites, también puedes invocarlo como command /opt/ast/bin/wc) lo que lo convierte en el más eficiente para archivos normales en ese shell.

Varios sistemas tienen un comando llamado stat que es una interfaz para las llamadas al sistema stat() o lstat().

Aquellos reportan información que se encuentra en el inodo. Una de esa información es el atributo st_size. En el caso de los archivos normales, ese es el tamaño del contenido (cuántos datos se pueden leer en ausencia de error (eso es lo que la mayoría de las implementaciones wc -c usan en su optimización) ). Para los enlaces simbólicos, ese es el tamaño en bytes de la ruta de destino. Para las canalizaciones con nombre, según el sistema, es 0 o el número de bytes actualmente en el búfer de la canalización. Lo mismo ocurre con los dispositivos de bloque donde, según el sistema, obtiene 0 o el tamaño en bytes del almacenamiento subyacente.

No necesita permiso de lectura del archivo para obtener esa información, solo permiso de búsqueda para el directorio al que está vinculado.

Por orden cronológico, existe:

  • IRIX stat (90 «s):

    stat -qLs -- "$file" 

    devuelve el atributo st_size de $file (lstat()) o:

    stat -s -- "$file" 

    lo mismo excepto cuando $file es un enlace simbólico, en cuyo caso es «el st_size del archivo después de la resolución del enlace simbólico.

  • zsh stat incorporado (ahora también conocido como zstat) en el módulo zsh/stat (cargado con zmodload zsh/stat) (1997):

    stat -L +size -- $file # st_size of file stat +size -- $file # after symlink resolution 

    o para almacenar en una variable:

    stat -L -A size +size -- $file 

    obviamente, eso es lo más eficiente en ese shell.

  • GNU stat (2001); también en BusyBox stat desde 2 005 (copiado de GNU stat):

    stat -c %s -- "$file" # st_size of file stat -Lc %s -- "$file" # after symlink resolution 

    (observe el significado de -L se invierte en comparación con IRIX o zsh stat.

  • BSD stat (2002):

    stat -f %z -- "$file" # st_size of file stat -Lf %z -- "$file" # after symlink resolution 

O puede usar la función stat() / lstat() de algún lenguaje de programación como perl:

perl -le "print((lstat shift)[7])" -- "$file" 

AIX también tiene un istat comando que volcará todos los stat() (no lstat(), por lo que no funcionará en enlaces simbólicos ) información y con la que podría procesar posteriormente, por ejemplo:

LC_ALL=C istat "$file" | awk "NR == 4 {print $5}" 

(gracias @JeffSchaller por el ayuda para averiguar los detalles ).

En tcsh:

@ size = -Z $file:q 

(tamaño después de la resolución del enlace simbólico)

Mucho antes de que GNU presentara su comando stat, se podía lograr lo mismo con GNU find comando con su -printf predicado (ya en 1991):

find -- "$file" -prune -printf "%s\n" # st_size of file find -L -- "$file" -prune -printf "%s\n" # after symlink resolution 

Sin embargo, un problema es que no funciona si $file comienza con - o es un find predicado (como !, ( …).

El comando estándar para obtener el stat() / lstat() la información es ls.

POSIXly, puede hacer:

LC_ALL=C ls -dn -- "$file" | awk "{print $5; exit}" 

y agregue -L para lo mismo después de la resolución del enlace simbólico. Eso no funciona para archivos de dispositivo, aunque el campo 5 th es el número principal del dispositivo en lugar del tamaño.

Para dispositivos de bloque, sistemas en los que stat() devuelve 0 para st_size, normalmente tienen otras API para informar el tamaño del dispositivo de bloque. Por ejemplo, Linux tiene BLKGETSIZE64 ioctl(), y la mayoría de las distribuciones de Linux ahora incluyen un comando blockdev que puede usarlo:

blockdev --getsize64 -- "$device_file" 

Sin embargo, necesita permiso de lectura para el archivo del dispositivo para eso. Por lo general, es posible derivar el tamaño por otros medios. Por ejemplo (todavía en Linux):

lsblk -bdno size -- "$device_file" 

Debería funcionar excepto para dispositivos vacíos.

Un enfoque que funciona para todos Los archivos buscables (por lo que incluye archivos normales, la mayoría de los dispositivos de bloqueo y algunos dispositivos de caracteres) es abrir el archivo y buscar el final:

  • Con zsh (después de cargar el módulo zsh/system):

    {sysseek -w end 0 && size=$((systell(0)))} < $file 
  • Con ksh93:

    < "$file" <#((size=EOF)) 

    o

    { size=$(<#((EOF))); } < "$file" 
  • con perl:

    perl -le "seek STDIN, 0, 2 or die "seek: $!"; print tell STDIN" < "$file" 

Para canalizaciones con nombre, hemos visto que algunos sistemas (AIX, Solaris, HP / UX al menos) hacen que la cantidad de datos en el búfer de canalización esté disponible en stat() «s st_size. Algunos (como Linux o FreeBSD) no lo hacen.

En Linux al menos, puede usar FIONREAD ioctl() después de haber abierto la tubería (en modo lectura + escritura para evitar que se cuelgue):

fuser -s -- "$fifo_file" && perl -le "require "sys/ioctl.ph"; ioctl(STDIN, &FIONREAD, $n) or die$!; print unpack "L", $n" <> "$fifo_file" 

Sin embargo, tenga en cuenta que si bien no lee el contenido de la tubería, la mera apertura de la tubería nombrada aquí todavía puede tener efectos secundarios. «Estamos usando fuser para verificar primero que algún proceso ya tiene la tubería abierta para aliviar eso, pero eso» no es infalible como fuser puede no ser capaz de comprobar todos los procesos.

Ahora, hasta ahora sólo hemos estado considerando el tamaño de los datos primarios asociados con los archivos.Eso no tiene en cuenta el tamaño de los metadatos y toda la infraestructura de apoyo necesaria para almacenar ese archivo.

Otro atributo de inodo devuelto por stat() es st_blocks. Ese es el número de bloques de 512 bytes que se utilizan para almacenar los datos del archivo (y a veces algunos de sus metadatos, como los atributos extendidos en los sistemas de archivos ext4 en Linux). Eso no «No incluye el inodo en sí, o las entradas en los directorios a los que está vinculado el archivo.

El tamaño y el uso del disco no están necesariamente estrechamente relacionados como compresión, escasez (a veces algunos metadatos), infraestructura adicional como bloques indirectos en algunos sistemas de archivos influye en este último.

Eso es típicamente lo que du usa para informar el uso del disco. La mayoría de los comandos enumerados anteriormente podrán obtener esa información.

  • POSIXLY_CORRECT=1 ls -sd -- "$file" | awk "{print $1; exit}"
  • POSIXLY_CORRECT=1 du -s -- "$file" (no para directorios donde eso incluiría el uso del disco e de los archivos incluidos).
  • GNU find -- "$file" -printf "%b\n"
  • zstat -L +block -- $file
  • GNU stat -c %b -- "$file"
  • BSD stat -f %b -- "$file"
  • perl -le "print((lstat shift)[12])" -- "$file"

Comentarios

  • claramente la respuesta más completa e informativa. gracias. Puedo usar esto para crear scripts bash multiplataforma usando la información de estadísticas de BSD y GNU
  • Dato curioso: GNU coreutils wc -c usa fstat, pero luego lee los últimos st_blksize bytes. Aparentemente esto se debe a que los archivos en Linux ‘ s /proc y /sys por ejemplo, tienen tamaños de estadísticas que son solo aproximados . Esto es bueno para la corrección, pero malo si el final del archivo está en el disco y no en la memoria (especialmente si se usa en muchos archivos en un bucle). Y muy malo si el archivo se migra a almacenamiento en cinta casi en línea o, por ejemplo, un sistema de archivos de descompresión transparente FUSE.
  • ¿No funcionaría esto también ls -go file | awk '{print $3}'
  • @StevenPenny esos -go serían los de SysV, no ‘ no funcionarían en BSD (opcional (XSI) en POSIX). ‘ d también necesita ls -god file | awk '{print $3; exit}' (-d para que funcione en directorios, exit para enlaces simbólicos con nuevas líneas en el destino). Los problemas con los archivos de dispositivo también persisten.
  • @ αғsнιη la API de Unix no hace distinción entre archivos de texto y binarios. Es ‘ todas las secuencias de bytes. Algunas aplicaciones pueden querer interpretar esos bytes como texto pero obviamente no wc -c que informa el número de bytes.

Respuesta

Este script combina muchas formas de calcular el tamaño del archivo:

( du --apparent-size --block-size=1 "$file" 2>/dev/null || gdu --apparent-size --block-size=1 "$file" 2>/dev/null || find "$file" -printf "%s" 2>/dev/null || gfind "$file" -printf "%s" 2>/dev/null || stat --printf="%s" "$file" 2>/dev/null || stat -f%z "$file" 2>/dev/null || wc -c <"$file" 2>/dev/null ) | awk "{print $1}" 

El script funciona en muchos sistemas Unix incluidos Linux, BSD, OSX, Solaris, SunOS, etc.

El tamaño del archivo muestra el número de bytes. Es el tamaño aparente, que son los bytes que usa el archivo en un disco típico, sin compresión especial, o áreas dispersas especiales, o bloques no asignados, etc.

Este script tiene una versión de producción con más ayuda y más opciones aquí: https://github.com/SixArm/file-size

Responder

stat parece hacer esto con la menor cantidad de llamadas al sistema:

$ set debian-live-8.2.0-amd64-xfce-desktop.iso $ strace stat --format %s $1 | wc 282 2795 27364 $ strace wc --bytes $1 | wc 307 3063 29091 $ strace du --bytes $1 | wc 437 4376 41955 $ strace find $1 -printf %s | wc 604 6061 64793 

La respuesta

ls -l filename le dará mucha información sobre un archivo, incluyendo su tamaño, permisos y propietario.

El tamaño del archivo en la quinta columna y se muestra en bytes. En el siguiente ejemplo, el tamaño es un poco menos de 2 KB:

-rw-r--r-- 1 user owner 1985 2011-07-12 16:48 index.php 

Editar: Esto aparentemente no es tan confiable como el comando stat.

Comentarios

  • Creo que los comandos ls -l y stat dan información de tamaño confiable. No encontré ninguna referencia en contrario. ls -s dará el tamaño en número de bloques.
  • @ dabest1 it ‘ no es confiable en un sentido que en otro unix, su salida puede ser diferente (y en algunos unix lo es).
  • Sí, IIRC, Solaris no ‘ t muestra el nombre del grupo por defecto, lo que lleva a menos columnas en la salida.
  • Dado que el tamaño es puramente numérico, rodeado por espacios en blanco, y la fecha del año es puramente numérica, en un formato definido, sería posible usar una expresión regular para tratar al usuario + propietario como un campo, tanto si el grupo estaba presente como si no. (¡un ejercicio para el lector!)

Responder

du filename le indicará el uso del disco en bytes.

Prefiero du -h filename, que le da el tamaño en un formato legible por humanos.

Comentarios

  • que o stat -c "%s"😉
  • Este sabor de du imprime el tamaño en bloques de 1024 bytes, no un simple recuento de bytes.
  • Note que el estándar du da una salida en unidades de 512 bytes. GNU du usa kibibytes en su lugar, a menos que se llame con POSIXLY_CORRECT en su entorno.
  • Para archivos de tipo directorio , que da el uso de disco del directorio pero también de todos los demás archivos dentro (recursivamente).

Respuesta

Cree pequeñas funciones de utilidad en sus scripts de shell en las que pueda delegar.

Ejemplo

#! /bin/sh - # vim: set ft=sh # size utility that works on GNU and BSD systems size(){ case $(uname) in (Darwin | *BSD*) stat -Lf %z -- "$1";; (*) stat -c %s -- "$1" esac } for f do printf "%s\n" "$f : $(gzip < "$f" | wc -c) bytes (versus $(size "$f") bytes)" done 

Basado en información de @ Stéphane Chazelas «respuesta.

Comentarios

  • Consulte también gzip -v < file > /dev/null para verificar la compresibilidad de un archivo.
  • @St é phaneChazelas no estoy seguro de si creo que fue una mejora. Esas declaraciones de casos pueden fácilmente desanimar a los novatos; ciertamente nunca recuerdo cómo hacerlas bien 🙂 son declaraciones de casos inherentemente más portátiles desde que Veo el punto cuando hay más de dos casos, pero por lo demás … +
  • Supongo que ‘ también es una cuestión de gustos, pero aquí ‘ es el caso típico en el que ‘ desearía utilizar un case declaración. case es la construcción de Bourne / POSIX para hacer coincidir patrones. [[...]] es ksh / bash / zsh solamente (con variaciones).

Respuesta

Encontré un trazador de líneas AWK 1, y tenía un error pero lo arreglé. También agregué PetaBytes después de TeraBytes.

FILE_SIZE=234234 # FILESIZE IN BYTES FILE_SIZE=$(echo "${FILE_SIZE}" | awk "{ split( "B KB MB GB TB PB" , v ); s=1; while( $1>1024 ){ $1/=1024; s++ } printf "%.2f %s", $1, v[s] }") 

Considerando stat no está en todos los sistemas, casi siempre puede usar la solución AWK. Ejemplo; la Raspberry Pi no tiene stat pero tiene awk .

Comentarios

  • Completamente NO lo que pidió el OP, pero un buen trabajo.

Responder

Me gusta la opción wc. Junto con «bc», puede obtener decimales en todos los lugares que desee.

Estaba buscando mejorar un script que tenía que awk «eliminaba la columna» tamaño de archivo «de un» ls – alh «. No quería sólo tamaños de archivo enteros, y dos decimales parecían encajar, así que después de leer esta discusión, se me ocurrió el siguiente código.

Sugiero romper la línea en el punto y coma si incluye esto en un script.

file=$1; string=$(wc -c $file); bite=${string% *}; okay=$(echo "scale=2; $bite/1024" | bc);friend=$(echo -e "$file $okay" "kb"); echo -e "$friend"

Mi El script se llama gpfl , para «obtener la longitud del archivo de imagen». Lo uso después de hacer un mogrify en un archivo en imagemagick, antes de abrir o volver a cargar una imagen en un visor jpeg de GUI.

No sé cómo califica esto una «respuesta», ya que toma prestado mucho de lo que ya se ha ofrecido y discutido. Así que lo dejaré ahí.

BZT

Comentarios

  • Preferiría usar » stat » o » ls «. Normalmente no ‘ t me gusta usar » wc » para obtener tamaños de archivo porque lee físicamente el archivo completo. Si tiene muchos archivos, o archivos particularmente grandes, esto puede llevar mucho tiempo. Pero su solución es creativa … + 1.
  • Estoy de acuerdo con la idea de usar » stat » sobre » wc » para, sin embargo, si usa » wc -c «, no se leerán datos; en su lugar, lseek se usará para calcular la cantidad de bytes en un archivo. lingrok.org/xref/coreutils/src/wc.c#228
  • @ bbaja42 : tenga en cuenta que GNU Coreutils lee el último bloque del archivo, en caso de que stat.st_size fuera solo una aproximación (como para Linux /proc y /sys archivos). Supongo que decidieron no complicar el comentario principal cuando agregaron esa lógica un par de líneas hacia abajo: lingrok.org/xref/coreutils/src/wc.c#246

Respuesta

El método más rápido y simple (IMO) es:

bash_var=$(stat -c %s /path/to/filename) 

Comentarios

  • Luego vota a favor de una o más de las respuestas existentes que mencionan stat; no es necesario repetirlo de nuevo …
  • @JeffSchaller Acabo de votar a favor de la respuesta de Stephane ‘ según sus instrucciones.Creo que es demasiado complicado para mis propósitos. Por eso publiqué esta respuesta simple para almas afines.
  • Gracias; es ‘ solo que una sexta instancia de una » stat » answer no ‘ t simplifica esta Q & A, pero preferiría que un nuevo lector se preguntara » ¿en qué se diferencia esta respuesta de las otras? » y genera más confusión en lugar de menos.
  • @JeffSchaller, supongo. Pero podría quejarme de las muchas du y wc respuestas que deberían tener un descargo de responsabilidad NUNCA HAGA ESTO en vida. Esta noche utilicé mi respuesta en una aplicación de la vida real y pensé que valía la pena compartirla. Supongo que todos tenemos nuestras opiniones encoge de hombros .

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *