Respuesta corta:
\ls -afq | wc -l
(Esto incluye .
y ..
, por lo tanto, reste 2.)
Cuando enumera los archivos en un directorio, pueden suceder tres cosas comunes:
- Enumerar los nombres de archivo en el directorio. Esto es ineludible: no hay forma de contar los archivos en un directorio sin enumerarlos.
- Ordenar los nombres de los archivos. Los comodines de Shell y el
ls
comando hacen eso.
- Llamar
stat
para recuperar metadatos sobre cada entrada de directorio, como si es un directorio.
El # 3 es el más caro con diferencia, ya que requiere cargar un inodo para cada archivo. En comparación, todos los nombres de archivo necesarios para el n. ° 1 se almacenan de forma compacta en unos pocos bloques. # 2 desperdicia algo de tiempo de CPU pero a menudo no es un factor decisivo.
Si no hay líneas nuevas en los nombres de archivo, un simple ls -A | wc -l
le indica cuántos archivos hay en el directorio. Tenga en cuenta que si tiene un alias para ls
, esto puede desencadenar una llamada a stat
(por ejemplo, ls --color
o ls -F
necesita saber el tipo de archivo, que requiere una llamada a stat
), así que desde la línea de comando, llame command ls -A | wc -l
o \ls -A | wc -l
para evitar un alias.
Si hay nuevas líneas en el nombre del archivo, si las nuevas líneas se enumeran o no depende de la variante de Unix. GNU coreutils y BusyBox se muestran ?
de forma predeterminada para una nueva línea, por lo que son seguros.
Llame ls -f
para enumerar las entradas sin ordenarlas (# 2). Esto se activa automáticamente -a
(al menos en los sistemas modernos). La -f
opción está en POSIX pero con estado opcional; la mayoría de las implementaciones lo admiten, pero no BusyBox. La opción -q
reemplaza los caracteres no imprimibles, incluidas las nuevas líneas por ?
; es POSIX pero no es compatible con BusyBox, así que omítalo si necesita soporte de BusyBox a expensas de contar en exceso los archivos cuyo nombre contiene un carácter de nueva línea.
Si el directorio no tiene subdirectorios, entonces la mayoría de las versiones de find
no invocarán stat
sus entradas (optimización del directorio hoja: un directorio que tiene un recuento de enlaces de 2 no puede tener subdirectorios, por lo find
que no necesita buscar los metadatos de las entradas a menos que condición como lo -type
requiere). Entonces, find . | wc -l
es una forma portátil y rápida de contar archivos en un directorio, siempre que el directorio no tenga subdirectorios y que ningún nombre de archivo contenga una nueva línea.
Si el directorio no tiene subdirectorios pero los nombres de los archivos pueden contener líneas nuevas, pruebe con uno de estos (el segundo debería ser más rápido si es compatible, pero puede que no sea notablemente).
find -print0 | tr -dc \\0 | wc -c
find -printf a | wc -c
Por otro lado, no use find
si el directorio tiene subdirectorios: incluso find . -maxdepth 1
llamadas stat
en cada entrada (al menos con GNU find y BusyBox find). Evita la clasificación (# 2) pero paga el precio de una búsqueda de inodo (# 3) que mata el rendimiento.
En el shell sin herramientas externas, puede ejecutar contar los archivos en el directorio actual con set -- *; echo $#
. Esto pierde archivos de puntos (archivos cuyo nombre comienza con .
) e informa 1 en lugar de 0 en un directorio vacío. Esta es la forma más rápida de contar archivos en directorios pequeños porque no requiere iniciar un programa externo, pero (excepto en zsh) pierde tiempo para directorios más grandes debido al paso de clasificación (# 2).
En bash, esta es una forma confiable de contar los archivos en el directorio actual:
shopt -s dotglob nullglob
a=(*)
echo ${#a[@]}
En ksh93, esta es una forma confiable de contar los archivos en el directorio actual:
FIGNORE='@(.|..)'
a=(~(N)*)
echo ${#a[@]}
En zsh, esta es una forma confiable de contar los archivos en el directorio actual:
a=(*(DNoN))
echo $#a
Si usted tiene el mark_dirs
conjunto de opciones, asegúrese de apagarlo: a=(*(DNoN^M))
.
En cualquier shell POSIX, esta es una forma confiable de contar los archivos en el directorio actual:
total=0
set -- *
if [ $# -ne 1 ] || [ -e "$1" ] || [ -L "$1" ]; then total=$((total+$#)); fi
set -- .[!.]*
if [ $# -ne 1 ] || [ -e "$1" ] || [ -L "$1" ]; then total=$((total+$#)); fi
set -- ..?*
if [ $# -ne 1 ] || [ -e "$1" ] || [ -L "$1" ]; then total=$((total+$#)); fi
echo "$total"
Todos estos métodos ordenan los nombres de los archivos, excepto el zsh.
ls -l|wc -l
estaría apagado por uno debido a los bloques totales en la primera línea dels -l
salida