Recuento recursivo de archivos en un directorio de Linux

728

¿Cómo puedo contar recursivamente archivos en un directorio de Linux?

Encontré esto:

find DIR_NAME -type f ¦ wc -l

Pero cuando ejecuto esto, devuelve el siguiente error.

find: las rutas deben preceder a la expresión: ¦

Robert Buckley
fuente
64
Está confundiendo la barra rota ¦(ASCII 166) con la barra vertical |(ASCII 124) utilizada para la canalización UNIX .
Skippy le Grand Gourou
77
@SkippyleGrandGourou ¿No se llama tubería?
DaveStephens
27
@DaveStephens Sí, también se llama así. También se llama un golpe de Sheffer, barra vertical, barra vertical, barra, línea vertical, barra vertical, barra, obelisco, glidus.
emlai
64
@zenith Lo llamo Bob.
Christopher
15
En RFC20 se llama "línea vertical". "Pipe" es el nombre del operador de shell, en lugar del nombre del símbolo. Así como *es el carácter ASCII "asterisco", pero "veces" en otros contextos.
delgado

Respuestas:

1327

Esto debería funcionar:

find DIR_NAME -type f | wc -l

Explicación:

  • -type f para incluir solo archivos.
  • |( y no¦ ) redirige findla salida estándar del wccomando a la entrada estándar del comando.
  • wc(abreviatura de recuento de palabras) cuenta líneas nuevas, palabras y bytes en su entrada ( documentos ).
  • -l para contar solo nuevas líneas.

Notas:

  • Reemplace DIR_NAMEcon .para ejecutar el comando en la carpeta actual.
  • También puede eliminar los -type fdirectorios para incluir (y enlaces simbólicos) en el recuento.
  • Es posible que este comando cuente en exceso si los nombres de archivo pueden contener caracteres de nueva línea.

Explicación de por qué su ejemplo no funciona:

En el comando que mostró, no utiliza el "Pipe" ( |) para conectar dos comandos, sino la barra rota ( ¦) que el shell no reconoce como un comando o algo similar. Es por eso que recibes ese mensaje de error.

paulsm4
fuente
27
El fen -type fsignifica archivos y wc -llíneas de conteo de palabras.
Serge Stroobandt
3
Elimine los -type fdirectorios para incluir en el recuento
phatblat
3
No hay necesidad de la -printbandera
Zoltán
3
Si existe alguna posibilidad de que los nombres de archivo contengan el carácter de nueva línea, es posible que desee utilizar la -print0bandera.
gaboroncancio
2
@gaboroncancio Eso no va a ayudar, a menos que alguna implementación de wctenga la opción de leer una lista terminada en nulo. Vea mi respuesta para una alternativa.
Vuelva a instalar Monica Please
100

Para el directorio actual:

find -type f | wc -l
Abhishek Maurya
fuente
55
Esta solución no tiene en cuenta el nombre de archivo que contiene nuevas líneas.
Kusalananda
2
Para el directorio actual, ni siquiera necesita el.
baptx
1
En realidad, en algunas plataformas, que no es necesario explicar en detallefind .
tripleee
1
@Kusalanandra Su comentario se aplica a casi todas las respuestas aquí.
tripleee
69

Si desea un desglose de cuántos archivos hay en cada directorio bajo su directorio actual:

for i in */ .*/ ; do 
    echo -n $i": " ; 
    (find "$i" -type f | wc -l) ; 
done

Eso puede ir todo en una línea, por supuesto. El paréntesis aclara qué salida wc -lse supone que está mirando ( find $i -type fen este caso).

Greg Bell
fuente
77
Podría atascarse en directorios con espacios en sus nombres. Cambiar la primera línea para find . -maxdepth 1 -type d -print0 | while IFS= read -r -d '' i ; doarreglarlo. Consulte ¿Cómo puedo leer un archivo (flujo de datos, variable) línea por línea (y / o campo por campo)?
Arch Stanton
44
Usar findpara el bucle externo es solo una complicación innecesaria. for i in */; do`
tripleee
función countit {para i en $ (find. -maxdepth 1 -type d); do file_count = $ (encuentra $ i -tipo f | wc -l); echo "$ file_count: $ i"; hecho }; countit | sort -n -r
Schneems
Finalmente esto es lo que necesitaba. Mis carpetas tienen miles de archivos para imprimirlos con el árbol o cualquier otra cosa no es una opción
lesolorzanov
Esto incluye ../ y no parece avanzar, lo que significa que no es regresivo.
Daniel Lefebvre
50

Puedes usar

$ tree

después de instalar el paquete del árbol con

$ sudo apt-get install tree

(en una máquina Debian / Mint / Ubuntu Linux).

El comando muestra no solo la cuenta de los archivos, sino también la cuenta de los directorios, por separado. La opción -L se puede usar para especificar el nivel máximo de visualización (que, por defecto, es la profundidad máxima del árbol de directorios).

Los archivos ocultos también se pueden incluir al proporcionar la -aopción.

lev
fuente
44
Esta es en realidad la forma más sencilla de ver la cantidad de directorios y archivos.
Lorem Ipsum Dolor
11
Desde la página del manual: Por defecto, el árbol no imprime archivos ocultos . Debe proporcionar la -aopción para incluirlos.
eee
3
Para instalar esto en macOS, use brewy ejecute brew install tree, preferiblemente después de ejecutar brew update.
Ashish Ahuja
44
También está imprimiendo todos los nombres de archivo, por lo que será lento si tiene muchos archivos.
Franck Dernoncourt el
2
Guau, muy buena herramienta, puede imprimir carpetas coloreadas, enumerar solo carpetas, salida como JSON. Puede enumerar 34k carpetas y 51k archivos en muy pocos segundos. ¡Viejo!
brasofilo
46

En mi computadora, rsynces un poco más rápido que find | wc -len la respuesta aceptada:

$ rsync --stats --dry-run -ax /path/to/dir /tmp

Number of files: 173076
Number of files transferred: 150481
Total file size: 8414946241 bytes
Total transferred file size: 8414932602 bytes

La segunda línea tiene el número de archivos, 150,481 en el ejemplo anterior. Como beneficio adicional, también obtiene el tamaño total (en bytes).

Observaciones:

  • la primera línea es un recuento de archivos, directorios, enlaces simbólicos, etc., todos juntos, por eso es más grande que la segunda línea.
  • ¡La opción --dry-run(o -npara abreviar) es importante para no transferir realmente los archivos!
  • Utilicé la -xopción para "no cruzar los límites del sistema de archivos", lo que significa que si lo ejecuta /y tiene discos duros externos conectados, solo contará los archivos en la partición raíz.
psmith
fuente
Me gusta tu idea de usar rsync aquí. ¡Nunca lo habría pensado!
Qeole
Gracias @Qeole, la idea no es mía. Lo leí hace varios años en algún lugar donde rsync es el más rápido para eliminar una carpeta con muchos archivos y subcarpetas, así que pensé que también podría ser rápido contar archivos.
psmith
1
Intenté esto. Después de ejecutar ambos dos veces de antemano para llenar el caché de fs, find ~ -type f | wc -ltomó 1.7 / 0.5 / 1.33 segundos (real / usuario / sys). rsync --stats --dry-run -ax ~ /xxxtomó 4.4 / 3.1 / 2.1 segundos. Eso es para aproximadamente 500,000 archivos en SSD.
delgado
No sé qué versión de rsync que utiliza, pero en 3.1.2 que es un poco más fácil de leer:Number of files: 487 (reg: 295, dir: 192)
MPes
rsync version 2.6.9 protocol version 29
Usé
20

Dado que los nombres de archivo en UNIX pueden contener nuevas líneas (sí, nuevas líneas), wc -lpodría contar demasiados archivos. Imprimiría un punto para cada archivo y luego contaría los puntos:

find DIR_NAME -type f -printf "." | wc -c
hek2mgl
fuente
1
Parece que esta es la única solución que maneja archivos con nuevas líneas en sus nombres. Votado
codeforester
2
Hola :) Me encantan las nuevas líneas en los nombres de archivo. Eso los hace más legibles.
hek2mgl
Quiero decir, ¡las nuevas líneas en los nombres de los archivos no son el contenido!
codeforester
1
Solo bromeaba ... Sí, siempre hay que tener en cuenta las nuevas líneas en los nombres de archivo. Podrían provenir de contenido malicioso o menos espectacular, de un error tipográfico.
hek2mgl
18

Combinando varias de las respuestas aquí juntas, la solución más útil parece ser:

find . -maxdepth 1 -type d -print0 |
xargs -0 -I {} sh -c 'echo -e $(find "{}" -printf "\n" | wc -l) "{}"' |
sort -n

Puede manejar cosas extrañas como nombres de archivos que incluyen espacios entre paréntesis e incluso nuevas líneas. También ordena la salida por el número de archivos.

También puede aumentar el número -maxdepthpara que también se cuenten los subdirectorios. Tenga en cuenta que esto puede llevar mucho tiempo, especialmente si tiene una estructura de directorio altamente anidada en combinación con un -maxdepthnúmero alto .

Sebastian Meine
fuente
¿Qué pasa con el echo -e? Supongo que lo pones para doblar las nuevas líneas, pero también destrozará cualquier otro espacio en blanco irregular e intentará expandir cualquier carácter comodín presente textualmente en los nombres de archivo. Simplemente iría con algo así find .* * -type d -execdir sh -c 'find . -type f -printf "\n" | wc -l; pwd'y viviría con cualquier aberración en la salida, o tal vez jugaría con Bash printf "%q"para imprimir el nombre del directorio.
tripleee
10

Si desea saber cuántos archivos y subdirectorios existen desde el directorio de trabajo actual, puede usar este one-liner

find . -maxdepth 1 -type d -print0 | xargs -0 -I {} sh -c 'echo -e $(find {} | wc -l) {}' | sort -n

Esto funcionará en sabor GNU, y solo omite el -e del comando echo para BSD Linux (por ejemplo, OSX).

Santrix
fuente
2
Excelente solucion! El único problema que encontré fue directorios con espacios o caracteres especiales. Agregue comillas donde se usa el nombre del directorio:find . -maxdepth 1 -type d -print0 | xargs -0 -I {} sh -c 'echo -e $(find "{}" | wc -l) "{}"' | sort -n
John Kary
1
Lo modifiqué un poco y funciona bastante bien para mí:find . -maxdepth 1 -type d -print0 | xargs -0 -I {} sh -c 'echo $(find {} | wc -l) \\t {}' | sort -rn | less
Wizek
Mis comentarios sobre la respuesta de @ Sebastian se aplican aquí también. El uso de echo -e(o simplemente `echo` como en el comentario anterior) en un nombre de directorio sin comillas cambia un problema por otro.
tripleee
8

Si desea evitar casos de error, no permita wc -lver archivos con líneas nuevas (que contará como 2+ archivos)

Por ejemplo, considere un caso en el que tenemos un solo archivo con un solo carácter EOL

> mkdir emptydir && cd emptydir
> touch $'file with EOL(\n) character in it'
> find -type f
./file with EOL(?) character in it
> find -type f | wc -l
2

Dado que al menos gnu wcno parece tener una opción para leer / contar una lista terminada en nulo (excepto de un archivo), la solución más sencilla sería no pasarle nombres de archivo, sino una salida estática cada vez que se encuentra un archivo, por ejemplo en el mismo directorio que el anterior

> find -type f -exec printf '\n' \; | wc -l
1

O si tu lo findsoporta

> find -type f -printf '\n' | wc -l
1 
Restablecer a monica por favor
fuente
7

Puedes usar el comando ncdu. Contará recursivamente cuántos archivos contiene un directorio de Linux. Aquí hay un ejemplo de salida:

ingrese la descripción de la imagen aquí

Tiene una barra de progreso, que es conveniente si tiene muchos archivos:

ingrese la descripción de la imagen aquí

Para instalarlo en Ubuntu:

sudo apt-get install -y ncdu

Punto de referencia: utilicé https://archive.org/details/cv_corpus_v1.tar (380390 archivos, 11 GB) como la carpeta donde se tiene que contar la cantidad de archivos.

  • find . -type f | wc -l: alrededor de 1m20s para completar
  • ncdu: alrededor de 1m20s para completar
Franck Dernoncourt
fuente
Eso calcula principalmente el uso del disco, no el número de archivos. Es probable que esta sobrecarga adicional no sea deseada. (además de la necesidad de instalar un paquete adicional para algo que se puede hacer con las utilidades POSIX estándar)
hek2mgl
@ hek2mgl Calcula la cantidad de archivos, como se muestra en rojo en la primera captura de pantalla. Me tomó unos minutos para ~ 2 millones de archivos, por lo que la velocidad no es tan mala.
Franck Dernoncourt
2
@ hek2mgl Agregué un punto de referencia reproducible en la respuesta, lo ejecuté dos veces y no vi ninguna diferencia entre find . -type f | wc -ly ncdu.
Franck Dernoncourt
2
Sí, parece que findestá bajo el capó ejecutando más o menos las mismas llamadas al sistema para las duque es el back-end ncdu. Solo los enderecé.
hek2mgl
1
@FranckDernoncourt me encantó. Tengo toneladas de archivos en una carpeta y tener una barra de progreso es un salvavidas. ¡Gracias por compartir!
Geek
6
tree $DIR_PATH | tail -1

Salida de muestra:

5309 directorios, 2122 archivos

Néstor Urquiza
fuente
4

Para determinar cuántos archivos hay en el directorio actual, ingrese ls -1 | wc -l. Esto wchace un recuento del número de líneas (-l)en la salida de ls -1. No cuenta con archivos de puntos. Tenga en cuenta que ls -l(que es una "L" en lugar de un "1" como en los ejemplos anteriores) que utilicé en versiones anteriores de este CÓMO realmente le dará un recuento de archivos uno mayor que el recuento real. Gracias a Kam Nejad por este punto.

Si desea contar solo archivos y NO incluir enlaces simbólicos (solo un ejemplo de lo que podría hacer), puede usar ls -l | grep -v ^l | wc -l(esta vez es una "L", no un "1", queremos una lista "larga" aquí) . grepbusca cualquier línea que comience con "l" (que indica un enlace) y descarta esa línea (-v).

Velocidad relativa: "ls -1 / usr / bin / | wc -l" tarda aproximadamente 1,03 segundos en un 486SX25 descargado (/ usr / bin / en esta máquina tiene 355 archivos). " ls -l /usr/bin/ | grep -v ^l | wc -l" toma aproximadamente 1.19 segundos.

Fuente: http://www.tldp.org/HOWTO/Bash-Prompt-HOWTO/x700.html

Sophy
fuente
2
ls -ldebe hacer statsyscall en cada archivo para leer su tamaño, mtime y otras propiedades, lo cual es lento. En directorios grandes (más de 100.000 archivos) la ejecución ls -lpuede llevar varios minutos. Entonces, para contar solo los archivos, úselos siempre ls -1 | wc -l.
Marki555
Un 486SX25, agradable
cam8001
ls -1aún puede ser lento en directorios grandes, porque tiene que ordenar los archivos. Simplemente printf '%s\n' *hace lo mismo y evita la lsllamada externa (que de todos modos es problemática ), pero la solución más eficiente es usar un comando que no realice ninguna clasificación, como find. (La salida global se ordena por el caparazón.)
tripleee
4

Si lo que necesita es contar un tipo de archivo específico de forma recursiva , puede hacer:

find YOUR_PATH -name '*.html' -type f | wc -l 

-l es solo para mostrar el número de líneas en la salida.

LeOn - Han Li
fuente
La extensión es parte del nombre de archivo y puede no representar el archivo TIPO
Waxhead
4

Con bash:

Cree una matriz de entradas con () y obtenga el recuento con #.

FILES=(./*); echo ${#FILES[@]}

Ok, eso no cuenta recursivamente los archivos, pero primero quería mostrar la opción simple. Un caso de uso común podría ser crear copias de respaldo de un archivo. Esto creará logfile.1, logfile.2, logfile.3 etc.

CNT=(./logfile*); mv logfile logfile.${#CNT[@]}

Conteo recursivo con bash 4+ globstarhabilitado (como lo menciona @tripleee)

FILES=(**/*); echo ${#FILES[@]}

Para obtener el recuento de archivos de forma recursiva, todavía podemos usar find de la misma manera.

FILES=(`find . -type f`); echo ${#FILES[@]}
nickl-
fuente
Soporte de conchas modernas **/*para enumeración recursiva. Todavía es menos eficiente que finden directorios grandes porque el shell tiene que ordenar los archivos en cada directorio.
tripleee
2

He escrito ffcnt para acelerar el recuento recursivo de archivos en circunstancias específicas: discos rotativos y sistemas de archivos que admiten mapeo de extensión.

Puede ser un orden de magnitud más rápido lso findbasado en enfoques, pero YMMV.

the8472
fuente
2

Para directorios con espacios en el nombre ... (basado en varias respuestas anteriores): imprima recursivamente el nombre del directorio con el número de archivos dentro de:

find . -mindepth 1 -type d -print0 | while IFS= read -r -d '' i ; do echo -n $i": " ; ls -p "$i" | grep -v / | wc -l ; done

Ejemplo (formateado para facilitar la lectura):

pwd
  /mnt/Vancouver/Programming/scripts/claws/corpus

ls -l
  total 8
  drwxr-xr-x 2 victoria victoria 4096 Mar 28 15:02 'Catabolism - Autophagy; Phagosomes; Mitophagy'
  drwxr-xr-x 3 victoria victoria 4096 Mar 29 16:04 'Catabolism - Lysosomes'

ls 'Catabolism - Autophagy; Phagosomes; Mitophagy'/ | wc -l
  138

## 2 dir (one with 28 files; other with 1 file):
ls 'Catabolism - Lysosomes'/ | wc -l
  29

La estructura del directorio se visualiza mejor usando tree:

tree -L 3 -F .
  .
  ├── Catabolism - Autophagy; Phagosomes; Mitophagy/
  │   ├── 1
  │   ├── 10
  │   ├── [ ... SNIP! (138 files, total) ... ]
  │   ├── 98
  │   └── 99
  └── Catabolism - Lysosomes/
      ├── 1
      ├── 10
      ├── [ ... SNIP! (28 files, total) ... ]
      ├── 8
      ├── 9
      └── aaa/
          └── bbb

  3 directories, 167 files

man find | grep mindep
  -mindepth levels
    Do not apply any tests or actions at levels less than levels
    (a non-negative integer).  -mindepth 1 means process all files
    except the starting-points.

ls -p | grep -v /(utilizado a continuación) es de la respuesta 2 en /unix/48492/list-only-regular-files-but-not-directories-in-current-directory

find . -mindepth 1 -type d -print0 | while IFS= read -r -d '' i ; do echo -n $i": " ; ls -p "$i" | grep -v / | wc -l ; done
./Catabolism - Autophagy; Phagosomes; Mitophagy: 138
./Catabolism - Lysosomes: 28
./Catabolism - Lysosomes/aaa: 1

Aplicación: quiero encontrar el número máximo de archivos entre varios cientos de directorios (todos de profundidad = 1) [salida a continuación nuevamente formateada para facilitar la lectura]:

date; pwd
    Fri Mar 29 20:08:08 PDT 2019
    /home/victoria/Mail/2_RESEARCH - NEWS

time find . -mindepth 1 -type d -print0 | while IFS= read -r -d '' i ; do echo -n $i": " ; ls -p "$i" | grep -v / | wc -l ; done > ../../aaa
    0:00.03

[victoria@victoria 2_RESEARCH - NEWS]$ head -n5 ../../aaa
    ./RNA - Exosomes: 26
    ./Cellular Signaling - Receptors: 213
    ./Catabolism - Autophagy; Phagosomes; Mitophagy: 138
    ./Stress - Physiological, Cellular - General: 261
    ./Ancient DNA; Ancient Protein: 34

[victoria@victoria 2_RESEARCH - NEWS]$ sed -r 's/(^.*): ([0-9]{1,8}$)/\2: \1/g' ../../aaa | sort -V | (head; echo ''; tail)

    0: ./Genomics - Gene Drive
    1: ./Causality; Causal Relationships
    1: ./Cloning
    1: ./GenMAPP 2
    1: ./Pathway Interaction Database
    1: ./Wasps
    2: ./Cellular Signaling - Ras-MAPK Pathway
    2: ./Cell Death - Ferroptosis
    2: ./Diet - Apples
    2: ./Environment - Waste Management

    988: ./Genomics - PPM (Personalized & Precision Medicine)
    1113: ./Microbes - Pathogens, Parasites
    1418: ./Health - Female
    1420: ./Immunity, Inflammation - General
    1522: ./Science, Research - Miscellaneous
    1797: ./Genomics
    1910: ./Neuroscience, Neurobiology
    2740: ./Genomics - Functional
    3943: ./Cancer
    4375: ./Health - Disease 

sort -VEs un tipo natural. ... Entonces, mi número máximo de archivos en cualquiera de esos directorios (Claws Mail) es 4375 archivos. Si dejo el pad ( https://stackoverflow.com/a/55409116/1904943 ) esos nombres de archivo, todos se nombran numéricamente, comenzando con 1, en cada directorio, y se rellenan con 5 dígitos en total, debería estar bien .


Apéndice

Encuentre el número total de archivos, subdirectorios en un directorio.

$ date; pwd
Tue 14 May 2019 04:08:31 PM PDT
/home/victoria/Mail/2_RESEARCH - NEWS

$ ls | head; echo; ls | tail
Acoustics
Ageing
Ageing - Calorie (Dietary) Restriction
Ageing - Senescence
Agriculture, Aquaculture, Fisheries
Ancient DNA; Ancient Protein
Anthropology, Archaeology
Ants
Archaeology
ARO-Relevant Literature, News

Transcriptome - CAGE
Transcriptome - FISSEQ
Transcriptome - RNA-seq
Translational Science, Medicine
Transposons
USACEHR-Relevant Literature
Vaccines
Vision, Eyes, Sight
Wasps
Women in Science, Medicine

$ find . -type f | wc -l
70214    ## files

$ find . -type d | wc -l
417      ## subdirectories
Victoria Stuart
fuente
0

Hay muchas respuestas correctas aquí. ¡Aquí está otro!

find . -type f | sort | uniq -w 10 -c

dónde .está la carpeta para buscar y 10es el número de caracteres para agrupar el directorio.

pez globo
fuente
-1

encontrar -tipo f | wc -l

O (si el directorio es el directorio actual)

encontrar . -tipo f | wc -l

usuario128364
fuente
Esto duplica al menos otra respuesta a esta misma pregunta.
Kusalananda
-1

Esto funcionará completamente bien. Corto simple Si desea contar la cantidad de archivos presentes en una carpeta.

ls | wc -l
Sahil Nagpal
fuente
3
En primer lugar, esto no responde la pregunta. La pregunta es sobre el recuento recursivo de archivos desde un directorio hacia adelante y el comando que muestra no lo hace. Además, con ls está contando directorios y archivos. Además, no hay razón para responder una pregunta anterior si no va a agregar nada nuevo y ni siquiera va a leer la pregunta correctamente. Por favor, abstenerse de hacerlo.
XFCC
-1

Este enfoque alternativo con filtrado para formato cuenta todos los módulos de kernel de grub disponibles:

ls -l /boot/grub/*.mod | wc -l
DanielK
fuente
-3
ls -l | grep -e -x -e -dr | wc -l 
  1. Larga lista
  2. filtrar archivos y directorios
  3. contar la línea filtrada sin
RAM
fuente