¿Cómo puedo obtener un recuento de archivos en un directorio usando la línea de comando?

193

Tengo un directorio con una gran cantidad de archivos. No veo un lsinterruptor para proporcionar el recuento. ¿Hay alguna magia de línea de comandos para obtener un recuento de archivos?

Blake
fuente
tree . | tailo tree -a . | tailincluir archivos / directorios ocultos, treees recursivo si eso es lo que quieres.
CodyChan

Respuestas:

240

Usando una definición amplia de "archivo"

ls | wc -l

(tenga en cuenta que no cuenta los archivos ocultos y supone que los nombres de los archivos no contienen caracteres de nueva línea).

Para incluir archivos ocultos (excepto .y ..) y evitar problemas con los caracteres de nueva línea, la forma canónica es:

find . ! -name . -prune -print | grep -c /

O recursivamente:

find .//. ! -name . -print | grep -c //
James Roth
fuente
23
wces un programa de "conteo de palabras". El -lcambio hace que cuente líneas. En este caso, cuenta las líneas en la salida de ls. Esta es siempre la forma en que me enseñaron a obtener un recuento de archivos para un directorio determinado, también.
Sandy
20
añada por favor nota que lslo hace ls -1si la salida es una pipa.
lesmana
66
eso no incluye todo en un directorio: ha perdido archivos de puntos y también recopila un par de líneas adicionales. Un directorio vacío aún devolverá 1 línea. Y si llama ls -la, obtendrá tres líneas en el directorio. Desea ls -lA | wc -lomitir las entradas .y ... Sin embargo, seguirás siendo uno por uno.
1
Un directorio vacío devuelve 0 para mí
James Roth
2
Un enfoque corregido, que no contaría dos veces los archivos con nuevas líneas en el nombre, sería este: ls -q | wc -launque tenga en cuenta que este enfoque todavía no contará los archivos ocultos, y que los directorios se contarán.
godlygeek
31

Para una definición estrecha de archivo:

 find . -maxdepth 1 -type f | wc -l
Maciej Piechotka
fuente
Y, por supuesto, puede omitir el -maxdepth 1recuento de archivos de forma recursiva (o ajustarlo para la profundidad de búsqueda máxima deseada).
user7089
1
Si tiene un archivo cuyo nombre contiene una nueva línea, este enfoque lo contará incorrectamente dos veces.
godlygeek
77
Un enfoque corregido, que no contaría dos veces los archivos con nuevas líneas en el nombre, sería este:find -maxdepth 1 -type f -printf "\n" | wc -l
godlygeek
+1 Permitir archivos ocultos e ignora directorios
Michael Durrant
14
ls -1 | wc -l

...

$ ls --help | grep -- '  -1'
    -1                         list one file per line

...

$ wc --help | grep -- '  -l'
    -l, --lines            print the newline counts

PD: Nota ls - <número-> | wc - <letter-l>

nicomen
fuente
10
La mayoría de las versiones de lshacer -1automáticamente cuando la salida es a una tubería.
Dennis Williamson
3
@Dennis, eso es interesante. No sabía que una aplicación podría decir que su salida se dirigía a una tubería.
xenoterracide
1
Edité esta versión ya que es más explícita. Sin embargo, sí ls usa -1 si está canalizado (pruébalo: ls | cat), encuentro que la sintaxis -1 es más explícita.
Gabe.
3
@xenoterracide: En Bash:[[ -p /dev/stdin ]] && echo "stdin is from a pipe"
Dennis Williamson el
2
En mis pruebas, fue significativamente más rápido proporcionar también la opción -f para evitar que ls clasifique los nombres de archivo. Desafortunadamente, aún obtienes la respuesta incorrecta si tus nombres de archivo contienen nuevas líneas.
Samuel Edwin Ward
10

Probablemente la respuesta más completa usando ls/ wcpair es

ls -Aq | wc -l

si desea contar archivos de puntos y

ls -q | wc -l

de otra manera.

  • -Aes contar archivos de puntos, pero omite .y ...
  • -qhacer lsreemplazar caracteres no gráficos, específicamente caracteres de nueva línea, con ?, haciendo que la salida sea 1 línea para cada archivo

Para obtener una salida de una línea desde el lsterminal (es decir, sin conectarlo wc), -1se debe agregar la opción.

(comportamiento de lsprobado con coreutils 8.23)

Frax
fuente
2
Como dijiste, -1no es necesario. En cuanto a "maneja las nuevas líneas de los nombres de archivos de manera sensata con la salida de la consola" , esto se debe al -qinterruptor (que debe usar en lugar de -bporque es portátil) que "obliga a escribir cada instancia de caracteres de nombre de archivo no imprimibles y caracteres <tab> como el carácter <question-mark> ('?'). Las implementaciones pueden proporcionar esta opción por defecto si la salida es a un dispositivo terminal ". Así por ejemplo, ls -Aq | wc -lpara contar todos los archivos / directorios o ls -qp | grep -c /para contar directorios único no ocultos, etc ...
don_crissti
Gracias por tu contribución. Cambiado -ba -q.
Frax
7

Si sabe que el directorio actual contiene al menos un archivo no oculto:

set -- *; echo "$#"

Esto es obviamente generalizable a cualquier glob.

En un guión, esto tiene el efecto secundario a veces desafortunado de sobrescribir los parámetros posicionales. Puede solucionarlo utilizando una subshell o con una función (versión Bourne / POSIX) como:

count_words () {
  eval 'shift; '"$1"'=$#'
}
count_words number_of_files *
echo "There are $number_of_files non-dot files in the current directory"

Una solución alternativa es $(ls -d -- * | wc -l). Si el glob es *, el comando se puede acortar a $(ls | wc -l). Analizar la salida de lssiempre me hace sentir incómodo, pero aquí debería funcionar siempre y cuando los nombres de los archivos no contengan nuevas líneas o lsse les escapen. Y $(ls -d -- * 2>/dev/null | wc -l)tiene la ventaja de manejar el caso de un globo no coincidente con gracia (es decir, devuelve 0 en ese caso, mientras que el set *método requiere pruebas complejas si el globo puede estar vacío).

Si los nombres de archivo pueden contener caracteres de nueva línea, se debe utilizar una alternativa $(ls -d ./* | grep -c /).

Cualquiera de esas soluciones que se basan en pasar la expansión de un globo lspuede fallar con un error de lista de argumentos demasiado largo si hay muchos archivos coincidentes.

Gilles
fuente
1
¿Realmente quieres crear 13,923 parámetros posicionales? Y debe hacer su variable local localo eliminarla: eval $1=$#o simplemente usar echo $#y hacer number_of_files=$(count_words *).
Dennis Williamson el
1
@ Dennis: parte del punto era evitar la bifurcación. Supongo que no es una preocupación del siglo XXI. Ok, admito que ya no me importan los shells que no son POSIX, por lo que podría haber evitado la variable temporal.
Gilles
¿Por qué restaste uno $#(no lo habías hecho antes de la edición)?
Dennis Williamson el
@Dennis: sigo evitando una bifurcación (bueno, hace una diferencia en máquinas con una CPU lenta, como enrutadores) y pasando un nombre de variable como $1. Entonces, lo que quiero contar es la cantidad de parámetros que no son el primer parámetro. (No puedo usar shiftporque necesito mantener el nombre de la variable.) (Umm, ahora si hubieras preguntado por la primera línea ...)
Gilles
@ Dennis: ahora que lo pienso, puedo usarlo shiftsi es el momento adecuado.
Gilles
7

He encontrado du --inodesútil, pero no estoy seguro de qué versión durequiere. Debería ser sustancialmente más rápido que los enfoques alternativos que utilizan findy wc.

En Ubuntu 17.10, funciona lo siguiente:

du --inodes      # all files and subdirectories
du --inodes -s   # summary
du --inodes -d 2 # depth 2 at most

Combinar con | sort -nrpara ordenar descendente por número de inodos que contienen.

krlmlr
fuente
5

Si usamos ls / wc pair si estamos agregando -U, será mucho más rápido (no ordenar).

ls -AqU | wc -l
Jbnair
fuente
1
-USin embargo, es específico de GNU.
Stéphane Chazelas
4

Después de instalar el comando del árbol, simplemente escriba:

tree

Si también quieres archivos ocultos:

tree -a

Si está utilizando Debian / Mint / Ubuntu Linux, escriba el siguiente comando para instalar el comando del árbol:

sudo apt-get install tree

La opción -L se usa para especificar el nivel máximo de visualización del árbol de directorios. El comando de árbol no solo cuenta la cantidad de archivos, sino también la cantidad de directorios, considerando tantos niveles del árbol de directorios como desee.

lev
fuente
Cuando escribo el árbol, obtengo una especie de salida del árbol en la pantalla del directorio en el que estoy pero no puedo ver dónde se muestra la cantidad de archivos.
charlesdarwin el
2
find -maxdepth 1 -type f -printf . | wc -c
  • -maxdepth 1lo hará no recursivo, findes recursivo por defecto
  • -type f incluirá solo archivos
  • -printf .Es un lindo toque. imprime un punto para cada archivo en lugar del nombre de archivo, y ahora puede manejar cualquier nombre de archivo y también guarda datos; solo tenemos que contar los puntos :)
  • | wc -c cuenta personajes
aude
fuente
1

Sin tubería, sin copia de cadena, sin tenedor, simplemente golpea un forro

$ fcount() { local f i=0; for f in *; do let i++; done; echo $i; }; fcount
DaboD
fuente
1
Da un valor de 1 si no hay archivos en el directorio. No cuenta archivos, cuenta archivos y directorios.
Steve
1

Aquí hay otra técnica similar a la que publicó Gilles :

word_count () { local c=("$@"); echo "${#c[@]}"; }
file_count=$(word_count *)

que crea una matriz con 13,923 elementos (si esa es la cantidad de archivos que hay).

Dennis Williamson
fuente
¿Cuál es el punto de esa cmatriz? word_count() { echo "$#"; }seria suficiente. El objetivo de la solución @Gilles es almacenar el recuento en una variable devuelta para evitar tener que usar la sustitución de comandos (que implica una bifurcación y una tubería en capas diferentes a ksh93).
Stéphane Chazelas
1
find . -type f -maxdepth 1 |  wc -l 

Esto puede enumerar solo los archivos en el directorio actual.

pappu
fuente
find . -type fencontrará archivos en el directorio actual y también, recursivamente, en subdirectorios.
Dhag
0

Prueba esto, espero que esta respuesta te ayude

echo $((`ls -l | wc -l` -1 ))
Tigre
fuente
0

Puedes consultar con:

ls -l | grep -v ^l | wc -l
AMIC MING
fuente
0

Mejorando algunas respuestas dadas antes pero esta vez haciendo explícitamente.

$ tree -L 1 | tail -n 1 | cut -d " " -f 3

Vale la pena notar el uso de algunos comandos amados como taily cut. Además, tenga en cuenta que el árbol no está disponible de forma predeterminada. El comando anterior captura primero la información sobre el directorio en el nivel 1, luego obtiene la última línea tail -n 1donde está nuestro objetivo y termina cuttomando la tercera palabra.

Por ejemplo, ubicando en /:

/ $ tree -L 1
.
├── 1
├── bin -> usr/bin
├── boot
├── dev
├── etc
├── home
├── lib -> usr/lib
├── lib64 -> usr/lib64
├── lost+found
├── media
├── mnt
├── opt
├── proc
├── root
├── run
├── sbin -> usr/sbin
├── srv
├── sys
├── tmp
├── usr
└── var

20 directories, 1 file
/ $ tree -L 1 | tail -n 1
20 directories, 1 file
/ $ tree -L 1 | tail -n 1 | cut -d " " -f 3
1

Entonces, ¿qué hay de preguntar el número de directorios?

jonaprieto
fuente
-2

Usa el treecomando, solo:

tree
usuario115186
fuente