Enumerar archivos de forma recursiva mostrando solo la ruta completa y el tamaño del archivo desde el símbolo del sistema de Windows

51

Estoy tratando de generar un archivo de texto que contenga el nombre del archivo (incluida la ruta completa) y el tamaño del archivo para todos los archivos en un directorio particular y cualquiera de sus subdirectorios (es decir, recursivamente). Idealmente, no quiero comas en el tamaño del archivo (¡pero me conformaré con ellas!)

El siguiente comando lo hace pero sin el tamaño del archivo:

dir /b /s /a:-D > results.txt

Un resultado de ejemplo se vería así:

C:\Users\Martin\Pictures\Table\original\PC120013.JPG  227298
C:\Users\Martin\Pictures\Table\original\PC120014.JPG  123234
C:\Users\Martin\Pictures\Table\original\PC120015.JPG  932344

No creo que esto sea posible usando dirsolo, aunque me encantaría que me demuestren lo contrario. ¿Hay alguna otra manera de hacer esto, usando solo los comandos que están disponibles desde el Símbolo del sistema?

Martin Wilson
fuente

Respuestas:

28

Esto debería hacerlo:

@echo off & for /f %a in ('dir /s /b') do echo %~fa %~za

No es muy eficiente ... ejecutarlo para carpetas que contienen una tonelada de archivos puede ser incompleto, así que pruébelo primero en carpetas pequeñas.

De "para /?" texto de ayuda (usé 'a' en lugar de 'I')

In addition, substitution of FOR variable references has been enhanced.
You can now use the following optional syntax:

%~I         - expands %I removing any surrounding quotes (")
%~fI        - expands %I to a fully qualified path name
%~dI        - expands %I to a drive letter only
%~pI        - expands %I to a path only
%~nI        - expands %I to a file name only
%~xI        - expands %I to a file extension only
%~sI        - expanded path contains short names only
%~aI        - expands %I to file attributes of file
%~tI        - expands %I to date/time of file
%~zI        - expands %I to size of file
%~$PATH:I   - searches the directories listed in the PATH
               environment variable and expands %I to the
               fully qualified name of the first one found.
               If the environment variable name is not
               defined or the file is not found by the
               search, then this modifier expands to the
               empty string

The modifiers can be combined to get compound results:

%~dpI       - expands %I to a drive letter and path only
%~nxI       - expands %I to a file name and extension only
%~fsI       - expands %I to a full path name with short names only
%~dp$PATH:I - searches the directories listed in the PATH
               environment variable for %I and expands to the
               drive letter and path of the first one found.
%~ftzaI     - expands %I to a DIR like output line
Brian Adkins
fuente
66
Golpeé un pequeño inconveniente usando esto: los archivos con espacios en el nombre del archivo no se registraron correctamente. Para solucionar esto, agregué un "tokens=*"mensaje de la siguiente manera@echo off & for /f "tokens=*" %a in ('dir /s /b') do echo %~fa %~za
Don Vince,
¿Cómo imprimirlo en un txtarchivo?
Saeed Neamati
3
Debería serfor /r %a in (*) do echo %~fa %~za
ZAB
1
@Saeed Neamati: aquí hay un ejemplo >> C:\Temp\VideoList.txt: los resultados de cualquier proceso anterior se escriben en un archivo de texto llamado VideoList . El uso de one > sobrescribirá el archivo ( si ya existe ) y el uso de >> agregará nuevos resultados al final si el archivo de texto ( si ya existe ). Si el archivo de texto aún no existe, este comando escribe un nuevo archivo con el nombre especificado.
user23715
esto me dio una lista de archivos * .dwg, sin el tamaño del archivo, a un archivo de texto:@echo off & for /f "tokens=*" %a in ('dir *.dwg /s /b') do echo %~fa >>dwgfiles.txt
CAD bloke
15

Alternativa n. ° 1: FOR / R es más intuitiva que la n. ° 2 para mí.
Alternativa # 2: FOR / F corrige el problema con "espacios en los nombres" en la sugerencia de BrianAdkins.
Alternativa # 3: FORFILES sería mi elección, excepto que la ruta está entre comillas dobles.

Brian u otros gurús pueden tener una solución más elegante o pueden sugerir una docena de otras soluciones, pero estas tres funcionan. Intenté usar FOR TOKENS pero luego tuve que quitar los encabezados y pies de página, así que volví al número 1. También consideré crear un pequeño archivo .bat y llamarlo, pero eso agrega otro archivo (aunque proporciona mayor flexibilidad, como lo haría una función).

Probé todas las alternativas con directorios y nombres de archivos con espacios incrustados, un nombre de archivo de más de 200 caracteres, un nombre de archivo sin extensión y en la raíz de una unidad pequeña (solo por tiempo; un poco lento, como sugirió Brian), pero entonces está buscando en el Explorador de Windows; es por eso que instalé la aplicación de búsqueda Everything).

Alternativa # 1: FOR / R

Mejor (?) Mientras intentaba descubrir por qué la solución de Brian no funcionó para mí, miré HELP FOR y decidí probar el enfoque / R. (Crear un archivo sería lo mismo que en la Alternativa # 2).

@echo off & for /R "c:\deletelater\folder with spaces" %A in (*.*) do echo %~fA %~zA

Ejemplo: funciona (directorio diferente al anterior para demostrar la recursividad)

@echo off & for /R "c:\deletelater" %A in (*.*) do echo %~fA %~zA
c:\DeleteLater\Name with Spaces.txt 19800676
c:\DeleteLater\NoSpacesLongName.txt 21745440
c:\DeleteLater\Folder with Spaces\2nd Name with Spaces.txt 5805492
c:\DeleteLater\Folder with Spaces\2ndNoSpacesLongName.txt 3870322
c:\DeleteLater\FolderNoSpaces\3rd Name with Spaces.txt 27874695
c:\DeleteLater\FolderNoSpaces\3rdNoSpacesLongName.txt 28726032

Alternativa # 2: FOR / F

BrianAdkins sugirió: @echo off & for /f %a in ('dir /s /b') do echo %~fa %~za

Una respuesta corregida es:

@echo off & for /f "delims=*" %A in ('dir /s /b') do echo %~fA %~zA 

Una respuesta más completa con directorios suprimidos y salida (adjunta) a un archivo es:

@echo Results on %DATE% for %CD% >> YourDirFile.txt & echo off & for /f "delims=*" %A in ('dir /s /b /a:-d') do echo %~fA %~zA >> YourDirFile.txt

Nota: "delims = *" especifica un carácter no permitido en los nombres de archivo.
Nota: el segundo comando también suprime los directorios a través de / a: -d.
Nota: El nombre de la variable FOR está en mayúscula para aclarar la distinción entre los parámetros variables y variables si alguien elige diferentes nombres de variables.
Nota: Se agregó al archivo solo para sonrisas ya que el OP solicitó la salida a un archivo.

Supongo que realmente debería verificar el estado de ECHO y restablecerlo también.

Problema: espacios en los nombres

La solución propuesta de Brian no maneja los nombres de archivos y carpetas que contienen espacios (al menos no en mi configuración de Vista).

Ejemplo: incorrecto (sin delimitaciones; incluye suprimir directorio por OP pero con tamaño antes y después del nombre de archivo para enfatizar)

Nombre y tamaño truncados (4 de 6 archivos incorrectos):

@echo off & for /f %A in ('dir /s /b /a:-d') do echo %~zA %~fA %~zA
 C:\DeleteLater\Name
21745440 C:\DeleteLater\NoSpacesLongName.txt 21745440
 C:\DeleteLater\Folder
 C:\DeleteLater\Folder
 C:\DeleteLater\FolderNoSpaces\3rd
28726032 C:\DeleteLater\FolderNoSpaces\3rdNoSpacesLongName.txt 28726032

Ejemplo: correcto (Nota de salida a la pantalla, no adjunta al archivo)

@echo off & for /f "delims=*" %A in ('dir /s /b /a:-d') do echo %~fA %~zA
C:\DeleteLater\Name with Spaces.txt 19800676
C:\DeleteLater\NoSpacesLongName.txt 21745440
C:\DeleteLater\Folder with Spaces\2nd Name with Spaces.txt 5805492
C:\DeleteLater\Folder with Spaces\2ndNoSpacesLongName.txt 3870322
C:\DeleteLater\FolderNoSpaces\3rd Name with Spaces.txt 27874695
C:\DeleteLater\FolderNoSpaces\3rdNoSpacesLongName.txt 28726032

Alternativa # 3: FORFILES (Problema de cotización)

Esta solución es directamente de los últimos dos ejemplos en la documentación FORFILES ( forfiles /?).

FORFILES /S /M *.doc /C "cmd /c echo @fsize"
FORFILES /M *.txt /C "cmd /c if @isdir==FALSE notepad.exe @file"

La combinación de estos ejemplos y escribir en un archivo produce la respuesta (casi):

forfiles /s  /c "cmd /c if @isdir==FALSE echo @path @fsize" >>ForfilesOut.txt

Tenga en cuenta que la ruta está entre comillas en la salida.
No importa si está activado echo ono no echo off.
Agregar una línea en blanco que separa cada directorio sería una extensión trivial del IF.

Precaución : ¡Usar la máscara/m *.*no devolverá archivos sin extensión (como el último archivo en el ejemplo)!

Aparte : esto escribe un archivo en cada directorio con contenido de ese directorio:
forfiles /s /c "cmd /c if @isdir==FALSE echo @path @fsize >>ForfilesSubOut.txt"no es lo que el OP quería pero a veces es útil.

Ejemplo: funciona (pero con la ruta completa entre comillas)

forfiles /s  /c "cmd /c if @isdir==FALSE echo @path @fsize"

"c:\DeleteLater\Name with Spaces.txt" 19800676
"c:\DeleteLater\NoSpacesLongName.txt" 21745440
"c:\DeleteLater\Folder with Spaces\2nd Name with Spaces.txt" 5805492
"c:\DeleteLater\Folder with Spaces\2ndNoSpacesLongName.txt" 3870322
"c:\DeleteLater\FolderNoSpaces\3rd Name with Spaces.txt" 27874695
"c:\DeleteLater\FolderNoSpaces\3rdNoSpacesLongName.txt" 28726032
"c:\DeleteLater\MoreFiles\A really really long file name that goes on and on 123456789 asdfghjkl zxcvnm qwertyuiop and still A really really long file name that goes on and on 123456789 qwertyuiop and still further roughly 225 characters by now.txt" 447
"c:\DeleteLater\MoreFiles\New Text Document no extension" 0

Este ejemplo incluye un directorio adicional con un nombre de archivo súper largo y un nombre de archivo sin extensión.

Problema: Ruta entre comillas

Entonces, ¿hay una manera fácil de eliminar las comillas no deseadas (?) Según el ejemplo de OP y guardar la Alternativa # 3: FORFILES. (Pregunta retórica: ¿Son las citas una característica o un defecto?)

BillR
fuente
1

Me doy cuenta de que esto requiere una utilidad adicional , pero puede lograrlo de manera bastante sucinta utilizando la utilidad sfk :

sfk cwd +run -yes "sfk list -size -tab $qfile +toclip"

sfk fromclip > C:\_temp\sfk_list_output.txt

( Obtuve el enfoque usando el comando sfk encadenando aquí )

rogersillito
fuente
1
powershell "dir | select name,length"

Esto puede ser una trampa en la pregunta de los OP. Sin embargo, la pregunta ya no es relevante en los sistemas modernos basados ​​en Windows. El alias Dir se usó para ayudar a dibujar el enlace lógico.

algún chico
fuente
2
Intenté esto (Windows 7). Se tardó más de 30 segundos en ejecutarse (en un directorio con 20 entradas) y no descendió a subdirectorios.
Scott
Para tener recursividad, cambie a: powershell "Get-ChildItem -Recurse| select name,length"
giorgiomugnaini
0

A continuación se muestra lo que solía localizar archivos de video misceláneos que ocupaban demasiado espacio en una unidad de red y escribir los resultados en un archivo de texto en una PC local.

Estoy publicando mi propia respuesta algo tardía por tres razones. Uno, me gustan las respuestas concisas. Dos, esta única línea de script funcionó en múltiples configuraciones para mí, incluso a través de una red. Tres, según el comentario potencialmente oscuro de Don Vince bajo la respuesta de Brian Adkins, el uso de tokens puede evitar problemas de los nombres de archivos con espacios en ellos.

for /f "tokens=*" %%a in ('dir H:\*.mov H:\*.avi H:\*.wmv H:\*.mp4 /s /b') do echo %%~fa %%~za >> C:\Temp\VideoList.txt

Noté que las rutas de archivo / nombres de archivo muy largos (cientos de caracteres) también pueden causar errores, pero la búsqueda no se bloqueará. Sin embargo, el camino no está completamente explorado para su (s) objetivo (s). Una vez señalado, puede compensar comenzando más profundamente en la estructura de carpetas para eliminar este error.

Esta página ss64 tiene una muy buena presentación del uso del comando dir , enumera todos los modificadores, muchas combinaciones de conmutadores y muestra varios ejemplos útiles de sintaxis adecuada. No es tan completo como las diversas comunidades de Stack Exchange, pero hay una clara claridad en la presentación una vez que se sienta cómodo con la línea de comandos / secuencias de comandos por lotes.

usuario23715
fuente
0

He llegado a esto con el siguiente comando:

(for /R "\path\to\directory\" %A in (*.*) do echo %~fA %~zA) | findstr /v "echo"

El resultado:

D:\Users\Natasha>(for /R ".\" %A in (*.*) do echo %~fA %~zA) | findstr /v "echo"


D:\Users\Natasha\Flowers_ (12).jpg 118886

D:\Users\Natasha\SomeFolder\data.txt 1241

D:\Users\Natasha\SomeFolder\CS\Counter-Strike_1.6.exe 272645624

PD: Esto se basa en la respuesta de BillR (Alternativa # 1). Sin embargo, en mi caso se cuelga con @echo off.

natasha
fuente
0

El comando "du" me parece bastante útil y funciona tanto en Windows como en Unix (lo usé para verificar si todos los archivos se copiaron al transferir muchos datos de una PC con Windows a un servidor web Linux):

du -ah "C:\your_dir" > "C:\file_list.txt"

salidas:

15  C:\your_dir/.htaccess
608 C:\your_dir/folder/hello.txt
1.0 C:\your_dir/folder/subfolder/test.txt
1.0 C:\your_dir/folder/subfolder
1.2M    C:\your_dir/folder/world.txt
1.2M    C:\your_dir/folder
9.0 C:\your_dir/no_file_ending
11  C:\your_dir/sample document 1.txt
684K    C:\your_dir/sample document 2 - äöüßÄÖÜáà.txt
1.9M    C:\your_dir

Sin embargo, solo pude ver correctamente los caracteres especiales en el Bloc de notas, no en el Bloc de notas ++ (debe ser algo de codificación ANSI / UTF-8, no hay tiempo para analizar exactamente en este momento). Además, no encontré una solución para mostrar el tamaño después del nombre del archivo. Use las opciones "b" o "k" en lugar de "h" para mostrar el tamaño en bytes o kilobytes. Tuve algunos problemas al ejecutar el comando fuera de la carpeta que quiero analizar. Así que mejor ingrese el comando en el directorio correcto ("C: \ your_dir" en este ejemplo) y especifíquelo en el comando.

Matthias Luh
fuente
-1

Omita la b en dir / b / s / a: -D> results.txt y los resultados deberían verse así (es decir, dir / s / a: -D> results.txt):

El volumen en la unidad H es ARCHIVOS El número de serie del volumen es C9EB-112E

Directorio de archivos H: \

29/09/2014 11:36 PM 0 testing.txt 1 Archivo (s) 0 bytes

Directorio de H: \ Video \ Action \ Comix

10/06/2012 09:51 AM 184,740 file1.txt 20/07/2012 06:21 AM
864,832 file2.txt 31/08/2009 08:47 PM 606,638 file3.txt 31/08/2009 09:07 PM 160,320 file4 .TXT

xyln
fuente
Esta no es una respuesta a la pregunta original. No produce el resultado que solicitó OP.
DavidPostill
-1
where * /t  

Sin complicarse demasiado, esto debería producir el resultado deseado. Dará un poco más de lo que solicitó el OP, pero pensé que valía la pena mencionarlo. Agregue el modificador / R para especificar un directorio que no sea el actual.

algún chico
fuente
1
Considere actualizar y confirmar que su respuesta funciona como lo intenté y recibo un mensaje de error, ERROR: Invalid syntax. Value expected for '/r'así que considere volver al tablero de dibujo y proporcionar la sintaxis correcta y edite su respuesta con el detalle correcto.
Pimp Juice IT
Considere ingresar el valor ... / R es el cambio de directorio, por defecto es el directorio actual si lo omite.
someguy
"Dará un poco más de lo que pidió el OP". ¿Estás bromeando?  where /?dice: “Por defecto, la búsqueda se realiza a lo largo del directorio actual y en las rutas especificadas por la variable de entorno PATH . "- por lo que su where * /tcomando enumera todos los archivos C:\Windows\System32, algunos subdirectorios C:\Program Filesy todos los demás directorios en PATH. Para mí, eso fue más de 3000 líneas. Considere editar su respuesta para que sea razonable. PD Sin  /R, no es recursivo.
Scott
DONDE / R. *.* trabajó para mi. / R. dice buscar de forma recursiva desde la ubicación especificada (en este caso, su directorio actual). El *. * Es el patrón que debe coincidir. Entonces WHERE / R% USERPROFILE% * .docx mostrará todos los archivos de palabras en la carpeta del usuario. (Tengo que escapar * con \ en estos comentarios)
ACS