Recuento de bytes de "ls -l <archivo aleatorio>" versus el de "wc -c <archivo aleatorio>"

25

¿Hay alguna situación posible cuando

ls -l file.txt

no muestra el mismo número de bytes que

wc -c file.txt

En un script encontré la comparación de esos dos valores. ¿Cuál podría ser la razón de eso? ¿Es posible tener conteos de bytes diferentes del mismo archivo?

Rokas.ma
fuente
2
¿Podría dar un poco de contexto a este script que encontró?
Kusalananda
Ver también unix.stackexchange.com/a/321502/22565
Stéphane Chazelas

Respuestas:

13

Sí, hay tales casos.

En el caso de los enlaces simbólicos en el sistema Linux con GNU ls, se ls -lmostrará el tamaño del enlace, mientras wc -cque resolverá el archivo real y leerá el número de bytes allí. A continuación puede ver que ls -linforma 29 bytes, mientras que wcinforma 172 bytes en el archivo real.

$ ls -l /etc/resolv.conf                                                                                                 
lrwxrwxrwx 1 root root 29 1月  17  2016 /etc/resolv.conf -> ../run/resolvconf/resolv.conf
$ wc -c /etc/resolv.conf                                                                                                 
172 /etc/resolv.conf
$ wc -c /var/run/resolvconf/resolv.conf                                                                                  
172 /var/run/resolvconf/resolv.conf
$ ls -l /var/run/resolvconf/resolv.conf                                                                                  
-rw-r--r-- 1 root root 172 1月  15 15:49 /var/run/resolvconf/resolv.conf

En el caso de sistemas de archivos virtuales , como/proc o /sys, muchos archivos aparecerán como de tamaño 0 ls -l. Bajo el /devsistema de archivos tenemos una variedad de archivos especiales, como dispositivos de caracteres y dispositivos de bloque: se wc -ccuelga de ellos y ls -lmuestra números mayores y menores en lugar de tamaño.

Las canalizaciones con nombre se informarán como 0bytes ls -c, pero en wc -crealidad leerán el contenido de la canalización, por lo que técnicamente le dirá cuántos datos hay en la canalización con nombre:

$ mkfifo named.pipe                                                                                                      
$ echo "This is a test" > named.pipe &
[1] 2129
$ ls -l named.pipe
prw-rw-r-- 1 xieerqi xieerqi 0 1月  16 08:40 named.pipe|
$ wc -c named.pipe
15 named.pipe
[1] + Done                 echo "This is a test" >named.pipe 

Para archivos normales, el tamaño debe ser igual.


El punto de ls -ly wc -c, y cómo funcionan también difiere. wc -cen realidad abre un archivo para leer (puedes verlo si corres, strace wc -c /etc/passwdpor ejemplo). ls -lsolo realiza stat()llamadas en esos. Esto también explica por qué en los /proc ls -lshows de tamaño 0: no puede registrar esos archivos porque no son "reales" o están almacenados en el disco duro / ssd. wc -cen su lugar, lee el contenido de ese archivo y calcula su tamaño.

Finalmente, ls -les solo una herramienta para enumerar elementos de forma interactiva. Rara vez es una buena opción para las secuencias de comandos. Cuando realmente necesite leer los datos, use wc -cen su lugar.

Tenga en cuenta que, para crear secuencias de comandos y evaluar el tamaño de un archivo, lsno es el mejor candidato. De hecho, es una de las prácticas comunes para evitar el análisis de lssalida . Úselo du -b para averiguar el tamaño de un archivo.

Sergiy Kolodyazhnyy
fuente
1
Una pequeña aclaración: los archivos virtuales (en /sys/, /proc/etc.) pueden proporcionar statinformación, si el implementador lo elige. La mayoría de las veces, no hay una razón convincente para hacerlo, por lo que se omite. Los ejemplos incluyen el /proc/kcoreque se informa como el tamaño de la memoria del núcleo direccionable (generalmente mucho más que la memoria física disponible).
Toby Speight
11

ls -l devolverá el tamaño del archivo informado por el sistema de archivos.

wc -cintentará leer el archivo para determinar el tamaño 'real'. Según mis observaciones, parece que primero intenta buscar hasta el final, y si esto no funciona, leerá todo el archivo, contando el tamaño a medida que avanza.

Esta es una descripción simple de lo que hacen las dos herramientas, pero conlleva una serie de implicaciones para los resultados:

lsdará una salida incorrecta para ciertos sistemas de archivos. Por ejemplo, los sistemas de archivos virtualizados como /procinformarán un tamaño de cero para muchos archivos, porque estos "archivos" no se almacenan físicamente en ningún lugar; se generan según lo requiera el software.

wcno funcionará en absoluto para archivos sin permisos de lectura, mientras lsque solo requiere permisos para enumerar el directorio (comparar ls -l /etc/shadowcon wc -c /etc/shadow).

Como se menciona en otras respuestas, el comportamiento de los enlaces simbólicos también es diferente. Debido a que wcintenta leerlos, termina leyendo el archivo al que apunta el enlace simbólico, mientras que lssolo consulta el sistema de archivos, informará el tamaño utilizado para almacenar el enlace simbólico.

Estoy seguro de que hay otras diferencias que aún no he pensado, pero pensé que daría una explicación clara y simple sobre la razón básica detrás de estas diferencias.

Muzer
fuente
+1 por mencionar permisos de lectura y seek(). Este parece ser el caso, después de ejecutar strace wc -lun par de archivos grandes.
Sergiy Kolodyazhnyy
¡+1 por agregar muchos más detalles que mi respuesta!
Cyclic3
6

Para un archivo normal, ls y wc llaman stat. Sin embargo, para un archivo de / proc o / sys, ls devuelve 0, pero wc devuelve un número diferente:

$ ls -l /proc/modules
-r--r--r--  1 root root 0 Jan 16 14:56 modules
                        ^ this one
$ wc -c /proc/modules
7621 modules

Esta es probablemente una forma de descubrir si algo es un archivo especial.

Cíclico3
fuente
2
wc -cpara mí al menos llama fstat, pero aparentemente para otros fines. Encuentra la longitud del archivo lseekhasta el final. En el caso de que esto devuelva un error, reades todo el archivo.
Muzer