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 hemos ls | wc -l
dicho 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 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)
$> find -maxdepth 1 -not -name "." -print
./file2.txt
./file1.txt
./FILE?NAME
./file3.txt
$> find -maxdepth 1 -not -name "." -printf "%i\n" | wc -l
4
Método # 2: globstar
Forma simple, rápida y mayormente portátil:
$ set -- *
$ echo $#
228
set
El 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/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 usar
items=( dir/* )
echo ${#items[@]}
según lo propuesto por steeldriver en los comentarios .
Truco similar al find
método que se usó wc
y globstar se puede usar stat
para 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 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
)
$> 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
Ver también
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