¿Cómo extraer una lista completa de tipos de extensión dentro de un directorio?

28

Dentro de un directorio, y recursivamente dentro de sus subdirectorios, lo que significa que cada directorio dentro de un directorio es procesado, ¿cómo compilo una lista completa de extensiones únicas dentro del directorio?

El sistema operativo es Windows XP con todas las actualizaciones actuales, pero estoy de acuerdo con ejecutar el script si puedo decir lo que está haciendo, aunque preferiría no tener que instalar dot-net, ya que realmente no me gusta.

errores
fuente

Respuestas:

29

Este script por lotes lo hará.

@echo off

set target=%~1
if "%target%"=="" set target=%cd%

setlocal EnableDelayedExpansion

set LF=^


rem Previous two lines deliberately left blank for LF to work.

for /f "tokens=*" %%i in ('dir /b /s /a:-d "%target%"') do (
    set ext=%%~xi
    if "!ext!"=="" set ext=FileWithNoExtension
    echo !extlist! | find "!ext!:" > nul
    if not !ERRORLEVEL! == 0 set extlist=!extlist!!ext!:
)

echo %extlist::=!LF!%

endlocal

Guárdelo como cualquier .batarchivo y ejecútelo con el comando batchfile(sustituya el nombre que haya nombrado) para enumerar el directorio actual o especifique una ruta con batchfile "path". Buscará todos los subdirectorios.

Si desea exportar a un archivo, use batchfile >filename.txt(o batchfile "path" >filename.txt).

Explicación

Todo antes de la for /f...línea simplemente configura las cosas: hace que el directorio de destino busque, habilita la expansión retardada, lo que me permite actualizar las variables en el bucle y define una nueva línea ( LF) que puedo usar para una salida más ordenada. Ah, y los %~1medios "obtienen el primer argumento, eliminando comillas" que evitan las comillas duplicadas, ver for /?.

El bucle usa ese dir /b /s /a:-d "%target%"comando, capturando una lista de todos los archivos en todos los subdirectorios bajo el objetivo.

%%~xiextrae la extensión de las rutas completas que dirdevuelve el comando.

Una extensión vacía se reemplaza con "FileWithNoExtension", para que sepa que existe dicho archivo; si agregué una línea vacía, no es tan obvio.

La lista actual completa si se envía a través de un findcomando, para garantizar la unicidad. La salida de texto del comando find se envía nul, esencialmente a un agujero negro, no lo queremos. Como siempre agregamos un :al final de la lista, también debemos asegurarnos de que la consulta de búsqueda finalice con un :para que no coincida con los resultados parciales; vea los comentarios.

El findcomando establece% ERRORLEVEL% , un valor de 0 indica que hubo una coincidencia. Entonces, si no es 0, la extensión actual no está en la lista hasta el momento y debe agregarse.

La línea de eco básicamente sale, y también reemplazo mis marcadores de posición ( :) con nuevas líneas para que se vea bien.

Mover
fuente
+1 @Bob: Respuesta increíble, agregar la explicación también fue de gran ayuda. Simplemente probé el script, revisé los resultados de la prueba y todo funcionó muy bien. ¡Gracias otra véz!
errores
1
¡Funcionó PERFECTAMENTE! Utilicé la siguiente sintaxis:batchfile "path" >filename.txt
lucaferrario
Gran guión! Pero hay un pequeño error: si la carpeta contiene archivos aaa.cssy zzz.cs, .csla secuencia de comandos no informará la extensión .
Goozak
1
@Goozak Whoops. Corregido ahora. Las maravillas de la búsqueda de texto ... tenían que asegurarse de que la consulta de búsqueda terminara :para forzarla a coincidir con los límites.
Bob
19

Aunque no cumpla estrictamente los requisitos para un script por lotes, he usado un script de PowerShell de una sola línea:

Get-Childitem C:\MyDirectory -Recurse | WHERE { -NOT $_.PSIsContainer } | Group Extension -NoElement | Sort Count -Desc > FileExtensions.txt

Potencialmente podría ejecutarlo desde la línea de comando / archivo por lotes:

Powershell -Command "& Get-Childitem C:\MyDirectory -Recurse | WHERE { -NOT $_.PSIsContainer } | Group Extension -NoElement | Sort Count -Desc > FileExtensions.txt"

No reclamo ningún crédito por ello y, por supuesto, necesitará instalar Powershell. Para las versiones más nuevas de Windows, no hay forma de evitar esto.

Si lo elimina C:\MyDirectory, se ejecutará en el directorio actual.

Al final producirá un FileExtensions.txt que contiene algo como lo siguiente:

+-------+------+
| Count | Name |
+-------+------+
| ----- | ---- |
| 8216  | .xml |
| 4854  | .png |
| 4378  | .dll |
| 3565  | .htm |
| ...   | ...  |
+-------+------+

Dependiendo de la estructura de su carpeta, ocasionalmente puede recibir errores que le notifican que tiene una ruta larga.

Get-ChildItem : The specified path, file name, or both are too long. The fully qualified file name must be less than 260 characters, and the directory name must be less than 248 characters.

Cualquier subdirectorio allí tampoco se analizará, pero los resultados de todo lo demás aún se mostrarán.

Dan Atkinson
fuente
Gracias, de acuerdo en que es una respuesta útil. En una nota no relacionada, un poco desconcertado de cómo ha publicado una sola respuesta, sin embargo, tiene la insignia "Fanatic" por visitar Superuser durante 100 días consecutivos. ¿Tiene el sitio marcado o algo así?
errores
La insignia fue otorgada en 2010 cuando aceché efectivamente, pero estoy mucho más activo en SO: stackoverflow.com/users/31532/dan-atkinson . :)
Dan Atkinson
4

Aquí hay una respuesta detallada usando PowerShell (con Windows XP tendrá que instalar PowerShell):

¡Hola, guionista! ¿Cómo puedo usar Windows PowerShell para elegir las extensiones de archivo únicas utilizadas en una colección de archivos?

RichardM
fuente
1
Si bien PowerShell es definitivamente mucho más fácil que la línea de comandos, está basado en .NET. Lo cual, desafortunadamente, va en contra de "Preferiría no tener que instalar dot-net".
Bob
1
+1 @ RichardM: De acuerdo con Bob. Además, el código relacionado con el recuento de instancias de extensión encontradas, sin saber nada sobre PowerShell, parece tener mucha memoria; es decir, en lugar de mantener un recuento de cada instancia, creo que crear una matriz para almacenar instancias duplicadas de una extensión para cada extensión, luego hacer un recuento para cada matriz de extensión al final, lo que para mí parece una forma muy extraña de contando instancias de extensión. ¿Me estoy perdiendo de algo? (Dicho esto, el primer one-liner de PowerShell es bueno, y lo probaría si no me desagrada la dotnet.)
errores el
1
Eso es justo. Esta pregunta puede atraer a los buscadores que están más abiertos a una solución de PowerShell. Eso sí, una buena búsqueda en Google también encontrará el enlace de arriba.
RichardM
3
+1 para este enlace. errores obvios no le gusta todo .net, pero eso no significa que la solución anterior sea la mejor solución a largo plazo para este problema. Cuantos más idiomas, mejor creo.
Steve Rathbone
1
Aquí hay otro enlace que aborda la búsqueda recursiva, usando powershell. robertbigec.wordpress.com/2011/01/07/…
goodeye
0

Para enumerar todas las extensiones únicas de cmd bajo la ruta que está usando:

Powershell -Command "Get-ChildItem . -Include *.* -Recurse | Select-Object Extension | Sort-Object -Property Extension -Unique"
kofifus
fuente
0

Me pareció útil cambiar

if "!ext!"=="" set ext=FileWithNoExtension

a

if "!ext!"=="" set ext=.FileWithNoExtension

y para cambiar

echo %extlist::=!LF!%

a

echo %extlist::=!LF!% > ext-list.txt

El archivo generado contenía (sin saltos de línea, pero no importa) .bat.pdf.skp.ai.png.jpg.tif.pcp.txt.lst.ttf.dfont.psd.indd.docx.PDF.JPG.gif.jpeg .dwg.exr.FileWithNoExtension.vrlmap.sat.bak.ctb

que pude usar para mi proyecto.

Steev43230
fuente