¿Cómo puedo encontrar todas las distintas extensiones de archivo en una jerarquía de carpetas?


En una máquina Linux me gustaría recorrer una jerarquía de carpetas y obtener una lista de todas las distintas extensiones de archivo dentro de ella.

¿Cuál sería la mejor manera de lograr esto desde un shell?

Author: GloryFish, 2009-12-03

13 answers

Prueba esto (no estoy seguro si es la mejor manera, pero funciona):

find . -type f | perl -ne 'print $1 if m/\.([^.\/]+)$/' | sort -u

Funciona de la siguiente manera:

  • Buscar todos los archivos de la carpeta actual
  • Imprime la extensión de los archivos si los hay
  • Hacer una lista ordenada única
 258
Author: Ivan Nevostruev,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-12-03 19:27:33

No hay necesidad de la tubería a sort, awk puede hacerlo todo:

find . -type f | awk -F. '!a[$NF]++{print $NF}'
 36
Author: SiegeX,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-12-10 20:18:14

Versión recursiva:

find . -type f | sed -e 's/.*\.//' | sed -e 's/.*\///' | sort -u

Si desea totales (cómo puede veces que se vio la extensión):

find . -type f | sed -e 's/.*\.//' | sed -e 's/.*\///' | sort | uniq -c | sort -rn

No recursivo (carpeta única):

for f in *.*; do printf "%s\n" "${f##*.}"; done | sort -u

He basado esto en esta publicación en el foro, el crédito debería ir allí.

 22
Author: ChristopheD,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-11-01 02:08:18

Powershell:

dir -recurse | select-object extension -unique

Gracias a http://kevin-berridge.blogspot.com/2007/11/windows-powershell.html

 17
Author: Simon R,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-11-01 02:06:57

Encuentra todo con un punto y muestra solo el sufijo.

find . -type f -name "*.*" | awk -F. '{print $NF}' | sort -u

Si sabes que todos los sufijos tienen 3 caracteres entonces

find . -type f -name "*.???" | awk -F. '{print $NF}' | sort -u

O con sed muestra todos los sufijos con uno a cuatro caracteres. Cambie {1,4} al rango de caracteres que espera en el sufijo.

find . -type f | sed -n 's/.*\.\(.\{1,4\}\)$/\1/p'| sort -u
 10
Author: user224243,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-12-03 21:47:59

Añadiendo mi propia variación a la mezcla. Creo que es el más simple del lote y puede ser útil cuando la eficiencia no es una gran preocupación.

find . -type f | grep -o -E '\.[^\.]+$' | sort -u
 6
Author: gkb0986,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-12-09 17:38:50

Probé un montón de respuestas aquí, incluso la "mejor" respuesta. Todos se quedaron cortos de lo que yo buscaba específicamente. Así que además de las últimas 12 horas de sentarse en el código regex para múltiples programas y leer y probar estas respuestas esto es lo que se me ocurrió que funciona EXACTAMENTE como quiero.

 find . -type f -name "*.*" | grep -o -E "\.[^\.]+$" | grep -o -E "[[:alpha:]]{2,16}" | awk '{print tolower($0)}' | sort -u
  • Encuentra todos los archivos que pueden tener una extensión.
  • Greps solo la extensión
  • Greps para extensiones de archivo entre 2 y 16 caracteres (simplemente ajuste los números si no se ajustan a su necesidad). Esto ayuda a evitar los archivos de caché y los archivos del sistema (el bit de archivo del sistema es buscar en la cárcel).
  • Awk para imprimir las extensiones en minúsculas.
  • Ordenar y traer solo valores únicos. Originalmente había intentado probar la respuesta awk, pero imprimiría dos veces los elementos que variaban en la sensibilidad de mayúsculas y minúsculas.

Si necesita un recuento de las extensiones de archivo, utilice el siguiente código

find . -type f -name "*.*" | grep -o -E "\.[^\.]+$" | grep -o -E "[[:alpha:]]{2,16}" | awk '{print tolower($0)}' | sort | uniq -c | sort -rn

Si bien estos métodos tardarán algún tiempo en completarse y probablemente no lo estén las mejores formas de resolver el problema, funcionan.

Actualizar: Per @ alpha_989 las extensiones de archivo largas causarán un problema. Eso se debe a la expresión regular original " [[: alpha:]] {3,6}". He actualizado la respuesta para incluir la expresión regular " [[: alpha:]] {2,16}". Sin embargo, cualquiera que use este código debe ser consciente de que esos números son el mínimo y máximo de cuánto tiempo se permite la extensión para la salida final. Cualquier cosa fuera de ese rango se dividirá en varias líneas en la salida.

Nota: Original post hizo leer " - Greps para extensiones de archivo entre 3 y 6 caracteres (solo ajustar los números si no se ajustan a su necesidad). Esto ayuda a evitar los archivos de caché y los archivos del sistema (el bit de archivo del sistema es buscar en la cárcel)."

Idea: Podría usarse para encontrar extensiones de archivo sobre una longitud específica a través de:

 find . -type f -name "*.*" | grep -o -E "\.[^\.]+$" | grep -o -E "[[:alpha:]]{4,}" | awk '{print tolower($0)}' | sort -u

Donde 4 es la longitud de las extensiones de archivo a incluir y luego encontrar también cualquier extensión más allá de esa longitud.

 5
Author: Shinrai,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-04-04 00:37:40

En Python usando generadores para directorios muy grandes, incluyendo extensiones en blanco, y obteniendo el número de veces que cada extensión aparece:

import json
import collections
import itertools
import os

root = '/home/andres'
files = itertools.chain.from_iterable((
    files for _,_,files in os.walk(root)
    ))
counter = collections.Counter(
    (os.path.splitext(file_)[1] for file_ in files)
)
print json.dumps(counter, indent=2)
 4
Author: Andres Buritica,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-12-16 05:34:54

Dado que ya hay otra solución que usa Perl:

Si tienes instalado Python también puedes hacer (desde el shell):

python -c "import os;e=set();[[e.add(os.path.splitext(f)[-1]) for f in fn]for _,_,fn in os.walk('/home')];print '\n'.join(e)"
 2
Author: ChristopheD,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-12-04 08:27:53

Ninguna de las respuestas hasta ahora tratan con nombres de archivo con nuevas líneas correctamente (excepto por ChristopheD, que acaba de llegar mientras estaba escribiendo esto). El siguiente no es un shell one-liner, pero funciona, y es razonablemente rápido.

import os, sys

def names(roots):
    for root in roots:
        for a, b, basenames in os.walk(root):
            for basename in basenames:
                yield basename

sufs = set(os.path.splitext(x)[1] for x in names(sys.argv[1:]))
for suf in sufs:
    if suf:
        print suf
 1
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-12-04 08:35:28

También podrías hacer esto

find . -type f -name "*.php" -exec PATHTOAPP {} +
 0
Author: jrock2004,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-03-25 17:27:04

Creo que la forma más simple y directa es

for f in *.*; do echo "${f##*.}"; done | sort -u

Se modifica en la 3ra manera de ChristopheD.

 0
Author: Robert,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-02-13 08:21:45

No creo que este haya sido mencionado todavía:

find . -type f -exec sh -c 'echo "${0##*.}"' {} \; | sort | uniq -c
 0
Author: Dmitry B.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-05-21 23:01:17