Lo 12que ves no es la cantidad de archivos, sino la cantidad de bloques de disco consumidos.
De info coreutils 'ls invocation':
For each directory that is listed, preface the files with a line
`total BLOCKS', where BLOCKS is the total disk allocation for all
files in that directory. The block size currently defaults to 1024
bytes, but this can be overridden (*note Block size::). The
BLOCKS computed counts each hard link separately; this is arguably
a deficiency.
El total va de 12a 20cuando lo usas en ls -lalugar de ls -lporque estás contando dos directorios adicionales: .y ... Está utilizando cuatro bloques de disco para cada directorio (vacío), por lo que su total va de 3 × 4 a 5 × 4. (Con toda probabilidad, está utilizando un bloque de disco de 4096 bytes para cada directorio; como infoindica la página, el la utilidad no verifica el formato del disco, pero asume un tamaño de bloque de a 1024menos que se indique lo contrario)
Si desea obtener simplemente la cantidad de archivos, puede intentar algo como
ls | wc -lfallará si hay archivos con una nueva línea en el nombre del archivo. Esto es más resistente:find . -mindepth 1 -maxdepth 1 -printf . | wc -c
Flimm
20
"si los nombres de archivo tienen una nueva línea" ... estremecimiento
Petah
8
Como se man lsle dirá, puede evitar los caracteres de control con -b(los escapa) u -q(los omite). Entonces, para contar, ls -1q | wc -les seguro y preciso para mostrar archivos no ocultos. ls -1qA | wc -lpara contar archivos ocultos (pero no .y ..). Estoy usando en -1lugar de -lporque eso debería ser más rápido.
Oli
18
user4556274 ya ha respondido el por qué . Mi respuesta solo sirve para proporcionar información adicional sobre cómo contar correctamente los archivos.
En la comunidad Unix, el consenso general es que analizar la salida de lses una muy, muy mala idea , ya que los nombres de archivo pueden contener caracteres de control o caracteres ocultos. Por ejemplo, debido a un carácter de nueva línea en un nombre de archivo, nos hemos ls | wc -ldicho que hay 5 líneas en la salida de ls(que sí tiene), pero en realidad solo hay 4 archivos en el directorio.
$> touch FILE$'\n'NAME
$> ls
file1.txt file2.txt file3.txt FILE?NAME
$> ls | wc -l
5
Método # 1: encontrar utilidad
El findcomando, que generalmente se usa para trabajar al analizar nombres de archivos, puede ayudarnos aquí imprimiendo el número de inodo . Ya sea un directorio o un archivo, solo tiene un número de inodo único. Por lo tanto, utilizando -printf "%i\n"y excluyendo a .través de -not -name "."podemos tener un recuento preciso de los archivos. (Tenga en cuenta el uso de -maxdepth 1para evitar el descenso recursivo en subdirectorios)
setEl comando se utiliza para establecer los parámetros posicionales del shell (las $<INTEGER>variables, como en echo $1). Esto a menudo se usa para evitar la /bin/shlimitación de la falta de matrices. Se puede encontrar una versión que realiza verificaciones adicionales en la respuesta de Gille en Unix y Linux.
En shells que admiten matrices, como bash, podemos usar
Truco similar al findmétodo que se usó wcy globstar se puede usar statpara contar números de inodo por línea:
$> LC_ALL=C stat ./* --printf "%i\n" | wc -l
4
Un enfoque alternativo es usar un comodín en forbucle. (Tenga en cuenta que esta prueba usa un directorio diferente para probar si este enfoque desciende a subdirectorios, lo que no es así: 16 es el número verificado de elementos en mi ~/bin)
$> count=0; for item in ~/bin/* ; do count=$(($count+1)) ; echo $count ; done | tail -n 1
16
Método # 3: otros idiomas / intérpretes
Python también puede manejar nombres de archivos problemáticos imprimiendo la longitud de una lista dada mi os.listdir()función (que no es recursiva, y solo listará elementos en el directorio dado como argumento).
$> python -c "import os ; print os.listdir('.')"
['file2.txt', 'file1.txt', 'FILE\nNAME', 'file3.txt']
$> python -c "import os ; print(len(os.listdir('.')))"
4
En bash, otra opción sería usar una matriz, por ejemplo items=( dir/* ); echo ${#items[@]}(agregar shopt -s dotglobpara incluir archivos ocultos).
steeldriver
1
La impresión de números de inodo facilita el filtrado de enlaces duros si lo desea, con find | sort -u | wc -l.
Peter Cordes
@steeldriver: creo que es poco probable que el método bash-array sea más rápido. Si desea que sea recursivo, debe usar items=( dir/** )(con shopt -s globstar), pero bash no aprovecha los metadatos adicionales de readdir, por lo que registra cada entrada de directorio para ver si es un directorio en sí. Muchos sistemas de archivos almacenan el tipo de archivo en la entrada del directorio, por lo que readdir puede devolverlo sin acceder a los inodos. (por ejemplo, el último XFS no predeterminado tiene esto, y creo que ext4 lo ha tenido por más tiempo). Si lo straceencuentra, verá muchas menos statllamadas al sistema que strah bash.
Peter Cordes
2
¿Por qué no solo usar print(len(os.listdir('.')))? Menos caracteres para escribir y también evita el acceso a atributos doblemente subrayados.
ls | wc -l
fallará si hay archivos con una nueva línea en el nombre del archivo. Esto es más resistente:find . -mindepth 1 -maxdepth 1 -printf . | wc -c
man ls
le dirá, puede evitar los caracteres de control con-b
(los escapa) u-q
(los omite). Entonces, para contar,ls -1q | wc -l
es seguro y preciso para mostrar archivos no ocultos.ls -1qA | wc -l
para contar archivos ocultos (pero no.
y..
). Estoy usando en-1
lugar de-l
porque eso debería ser más rápido.user4556274 ya ha respondido el por qué . Mi respuesta solo sirve para proporcionar información adicional sobre cómo contar correctamente los archivos.
En la comunidad Unix, el consenso general es que analizar la salida de
ls
es una muy, muy mala idea , ya que los nombres de archivo pueden contener caracteres de control o caracteres ocultos. Por ejemplo, debido a un carácter de nueva línea en un nombre de archivo, nos hemosls | wc -l
dicho que hay 5 líneas en la salida dels
(que sí tiene), pero en realidad solo hay 4 archivos en el directorio.Método # 1: encontrar utilidad
El
find
comando, que generalmente se usa para trabajar al analizar nombres de archivos, puede ayudarnos aquí imprimiendo el número de inodo . Ya sea un directorio o un archivo, solo tiene un número de inodo único. Por lo tanto, utilizando-printf "%i\n"
y excluyendo a.
través de-not -name "."
podemos tener un recuento preciso de los archivos. (Tenga en cuenta el uso de-maxdepth 1
para evitar el descenso recursivo en subdirectorios)Método # 2: globstar
Forma simple, rápida y mayormente portátil:
set
El comando se utiliza para establecer los parámetros posicionales del shell (las$<INTEGER>
variables, como enecho $1
). Esto a menudo se usa para evitar la/bin/sh
limitación de la falta de matrices. Se puede encontrar una versión que realiza verificaciones adicionales en la respuesta de Gille en Unix y Linux.En shells que admiten matrices, como
bash
, podemos usarsegún lo propuesto por steeldriver en los comentarios .
Truco similar al
find
método que se usówc
y globstar se puede usarstat
para contar números de inodo por línea:Un enfoque alternativo es usar un comodín en
for
bucle. (Tenga en cuenta que esta prueba usa un directorio diferente para probar si este enfoque desciende a subdirectorios, lo que no es así: 16 es el número verificado de elementos en mi~/bin
)Método # 3: otros idiomas / intérpretes
Python también puede manejar nombres de archivos problemáticos imprimiendo la longitud de una lista dada mi
os.listdir()
función (que no es recursiva, y solo listará elementos en el directorio dado como argumento).Ver también
fuente
items=( dir/* ); echo ${#items[@]}
(agregarshopt -s dotglob
para incluir archivos ocultos).find | sort -u | wc -l
.items=( dir/** )
(conshopt -s globstar
), pero bash no aprovecha los metadatos adicionales de readdir, por lo que registra cada entrada de directorio para ver si es un directorio en sí. Muchos sistemas de archivos almacenan el tipo de archivo en la entrada del directorio, por lo que readdir puede devolverlo sin acceder a los inodos. (por ejemplo, el último XFS no predeterminado tiene esto, y creo que ext4 lo ha tenido por más tiempo). Si lostrace
encuentra, verá muchas menosstat
llamadas al sistema que strah bash.print(len(os.listdir('.')))
? Menos caracteres para escribir y también evita el acceso a atributos doblemente subrayados.