Iterar todos los archivos en un directorio usando un ciclo 'for'

353

¿Cómo puedo iterar sobre cada archivo en un directorio usando un forbucle?

¿Y cómo podría saber si cierta entrada es un directorio o si es solo un archivo?

Vhaerun
fuente
1
suponiendo que se refería al shell de Windows predeterminado, he vuelto a etiquetar su publicación para tener un poco más de claridad
David Schmitt
2
Especifique también qué versión de Windows está utilizando.
JOP
1
Esto debe dividirse en dos preguntas separadas, ya que son independientes entre sí.
julealgon

Respuestas:

493

Esto enumera todos los archivos (y solo los archivos) en el directorio actual:

for /r %i in (*) do echo %i

Además, si ejecuta ese comando en un archivo por lotes, debe duplicar los signos de%.

for /r %%i in (*) do echo %%i

(gracias @agnul)

jop
fuente
73
Si no desea utilizar esto de forma recursiva, asegúrese de sacar el / r
jocull
28
Si desea hacer eco solamente los nombres de archivo (no la ruta completa) con sus extensiones en el directorio actual (de forma recursiva), puede hacerlo de esta manera: for /r %i in (*) do ( echo %~nxi ). Este hilo también puede ser realmente útil: stackoverflow.com/questions/112055/… .
Sk8erPeter
2
@ Vaccano sí, después del Do, usa paréntesis. Es decir, hacer (echo% i & del% i). También puede usar "enter" en lugar de "&" para múltiples comandos.
Jay
2
Si está utilizando comandos como copiar / mover en lugar de echo, asegúrese de citar la ruta correctamente. para / r %% i en (*) do echo "%% i"
Soundararajan
2
Aparentemente necesita usar nombres de variables de una letra.
Álvaro González el
214

Iterar a través de ...

  • ... archivos en el directorio actual: for %f in (.\*) do @echo %f
  • ... subdire en el directorio actual: for /D %s in (.\*) do @echo %s
  • ... archivos en actual y todos subdirectorios: for /R %f in (.\*) do @echo %f
  • ... subdires en actual y todos subdirs: for /R /D %s in (.\*) do @echo %s

Desafortunadamente, no encontré ninguna forma de iterar sobre archivos y subdirecciones al mismo tiempo.

Simplemente use cygwin con su bash para mucha más funcionalidad.

Aparte de esto: ¿Notó que la ayuda de compilación de MS Windows es un gran recurso para las descripciones de la sintaxis de la línea de comandos de cmd?

También eche un vistazo aquí: http://technet.microsoft.com/en-us/library/bb490890.aspx

Marco
fuente
21
%filey %subdirsólo puede ser un carácter de longitud, es decir %f, %s.
Felix Dombek
1
el "subdirectorio en el directorio actual" no funciona. Recibo un error: s fue inesperado en este momento
Migrate2Lazarus ver mi perfil
78

Para iterar sobre cada archivo, un bucle for funcionará:

for %%f in (directory\path\*) do ( something_here )

En mi caso, también quería el contenido del archivo, el nombre, etc.

Esto condujo a algunos problemas y pensé que mi caso de uso podría ayudar. Aquí hay un bucle que lee información de cada archivo '.txt' en un directorio y le permite hacer algo con él (por ejemplo, setx).

@ECHO OFF
setlocal enabledelayedexpansion
for %%f in (directory\path\*.txt) do (
  set /p val=<%%f
  echo "fullname: %%f"
  echo "name: %%~nf"
  echo "contents: !val!"
)

* Limitación: val <= %% f solo obtendrá la primera línea del archivo.

Aaron Votre
fuente
18
Ah, un ejemplo de varias líneas. ¡Gracias por eso!
Nyerguds
@ Aaron Votre ¿Cómo terminar un ciclo?
nijogeorgep
@nijogeorgep No tiene que "finalizar" el ciclo. En mi ejemplo, todo lo que está dentro de los paréntesis (echo, etc.) se ejecutará una vez para cada archivo '* .txt' en el directorio. Creo que la respuesta que está buscando podría explicarse mejor aquí: stackoverflow.com/questions/1355791/…
Aaron Votre
@ Aaron Votre Estaba tratando de ejecutar algunos comandos maven usando un script, pero se estaba ejecutando como un bucle infinito, así que lo pedí. Comprar ahora agregué una salida a mi bucle y solucioné mi problema
nijogeorgep
@nijogeorgep ¡Me alegra que lo hayas descubierto!
Aaron Votre
57

Existe una sutil diferencia entre ejecutar FORdesde la línea de comandos y desde un archivo por lotes. En un archivo por lotes, debe poner dos% caracteres delante de cada referencia de variable.

Desde una línea de comando:

FOR %i IN (*) DO ECHO %i

De un archivo por lotes:

FOR %%i IN (*) DO ECHO %%i
aforia
fuente
44

Este bucle for mostrará una lista de todos los archivos en un directorio.

pushd somedir
for /f "delims=" %%f in ('dir /b /a-d-h-s') do echo %%f
popd

"delims =" es útil para mostrar nombres de archivo largos con espacios ...

'/ b "muestra solo nombres, no fechas de tamaño, etc.

Algunas cosas que debes saber sobre el argumento de dir / a.

  • Cualquier uso de "/ a" enumeraría todo, incluidos los atributos ocultos y del sistema.
  • "/ ad" solo mostraría subdirectorios, incluidos los ocultos y los del sistema.
  • El argumento "/ ad" elimina el contenido con el atributo 'D'irectory.
  • "/ adhs" mostrará todo, pero las entradas con 'D'irectory,' H'idden 'S'ystem atributo.

Si usa esto en la línea de comandos, elimine un "%".

Espero que esto ayude.

Arrendajo
fuente
10

% 1 se refiere al primer argumento pasado y no se puede usar en un iterador.

Prueba esto:

@echo off
for %%i in (*.*) do echo %%i
Sam Meldrum
fuente
Tienes razón. Intenté en modo inmediato verificar la sintaxis FOR y pegué la línea directamente en la respuesta olvidando los parámetros :-)
Axeman
5
for %1 in (*.*) do echo %1

Pruebe "AYUDA PARA" en cmd para obtener una guía completa

Esta es la guía para los comandos XP. http://www.ss64.com/nt/

Axeman
fuente
4

Para recorrer todos los archivos y carpetas , puede usar

for /F "delims=" %%a in ('dir /b /s') do echo %%a

Para iterar a través de todas las carpetas solo no con archivos, entonces puede usar

for /F "delims=" %%a in ('dir /a:d /b /s') do echo %%a

Donde /sdará todos los resultados en todo el árbol de directorios en profundidad ilimitada. Puede omitir /ssi desea recorrer el contenido de esa carpeta, no su subcarpeta

Implementando búsqueda en iteración

Para iterar a través de un determinado archivo con nombre y carpetas , puede buscar el nombre e iterar usando el bucle

for /F "delims=" %%a in ('dir "file or folder name" /b /s') do echo %%a

Para iterar a través de carpetas / directorios con nombre en particular y no archivos , luego use /ADel mismo comando

for /F "delims=" %%a in ('dir "folder name" /b /AD /s') do echo %%a
jafarbtech
fuente
4

Tuve problemas para obtener la respuesta de jop para trabajar con una ruta absoluta hasta que encontré esta referencia: https://ss64.com/nt/for_r.html

El siguiente ejemplo recorre todos los archivos en un directorio dado por la ruta absoluta.

For /R C:\absoulte\path\ %%G IN (*.*) do (
  Echo %%G
)
datchung
fuente
3

El siguiente código crea un archivo denominado "AllFilesInCurrentDirectorylist.txt" en el directorio actual, que contiene la lista de todos los archivos (solo archivos) en el directorio actual. Echale un vistazo

dir /b /a-d > AllFilesInCurrentDirectorylist.txt
Ankur
fuente
3

También podría usar el comando forfiles :

forfiles /s 

y también verifique si es un directorio

forfiles /p c:\ /s /m *.* /c "cmd /c if @isdir==true echo @file is a directory"
Max
fuente
@isdir==truenecesita ser@isdir==TRUE
psyklopz
2

Usaría vbscript (Windows Scripting Host), porque en lote estoy seguro de que no puedes decir que un nombre es un archivo o un directorio.

En vbs, puede ser algo como esto:

Dim fileSystemObject
Set fileSystemObject = CreateObject("Scripting.FileSystemObject")

Dim mainFolder
Set mainFolder = fileSystemObject.GetFolder(myFolder)

Dim files
Set files = mainFolder.Files

For Each file in files
...
Next

Dim subFolders
Set subFolders = mainFolder.SubFolders

For Each folder in subFolders
...
Next

Verifique FileSystemObject en MSDN .

Biri
fuente
Hubiera usado perl para hacer esto. Lamentablemente, no depende de mí.
Vhaerun
Alguna vieja aplicación? Cosas tristes
Biri
Un desarrollador idiota vio archivos por lotes y pensó que eran la cura para todos nuestros problemas.
Vhaerun
1
@Vhaerun Una ventaja de Windows Script Host (WSH) sobre Perl sería que WSH viene preinstalado con todas las versiones de Windows, mientras que Perl debería instalarse por separado, lo que puede o no ser una opción viable en todos los casos.
Parampreet Dhatt
2

Uso el comando xcopy con la opción / L para obtener los nombres de los archivos. Entonces, si desea obtener un directorio o todos los archivos en el subdirectorio, puede hacer algo como esto:

for /f "delims=" %%a IN ('xcopy "D:\*.pdf" c:\ /l') do echo %%a

Solo uso c: \ como destino porque siempre existe en los sistemas Windows y no se está copiando, por lo que no importa. si quieres los subdirectorios también usa la opción / s al final. También puede usar los otros interruptores de xcopy si los necesita por otros motivos.

Knoots
fuente
2

Pruebe esto para probar si un archivo es un directorio:

FOR /F "delims=" %I IN ('DIR /B /AD "filename" 2^>^&1 ^>NUL') DO IF "%I" == "File Not Found" ECHO Not a directory

Esto solo le dirá si un archivo NO es un directorio, lo que también será cierto si el archivo no existe, así que asegúrese de verificarlo primero si es necesario. Las marcas (^) se usan para escapar de los símbolos de redireccionamiento y la salida de la lista de archivos se redirige a NUL para evitar que se muestre, mientras que la salida de error de la lista de DIR se redirige a la salida para que pueda probar el mensaje "Archivo no encontrado" de DIR ".

sugerfunk
fuente
2

prueba esto:

::Example directory
set SetupDir=C:\Users

::Loop in the folder with "/r" to search in recursive folders, %%f being a loop ::variable 
for /r "%SetupDir%" %%f in (*.msi *.exe) do set /a counter+=1

echo there are %counter% files in your folder

cuenta archivos .msi y .exe en su directorio (y en el subdirectorio). Por lo tanto, también hace la diferencia entre carpetas y archivos como ejecutables.

Simplemente agregue una extensión (.pptx .docx ..) si necesita filtrar otros archivos en el bucle

Pequeño pony
fuente
1

En mi caso, tuve que eliminar todos los archivos y carpetas debajo de una carpeta temporal. Así es como terminé haciéndolo. Tuve que ejecutar dos bucles, uno para el archivo y otro para las carpetas. Si los archivos o carpetas tienen espacios en sus nombres, entonces debe usar ""

cd %USERPROFILE%\AppData\Local\Temp\
rem files only
for /r %%a in (*) do (
echo deleting file "%%a" ...
if exist "%%a" del /s /q "%%a"
)
rem folders only
for /D %%a in (*) do (
echo deleting folder "%%a" ...
if exist "%%a" rmdir /s /q "%%a"
)
Sam B
fuente
1

Aquí está mi ir con comentarios en el código.

Solo estoy repasando las habilidades de biatch, así que perdona cualquier error evidente.

Traté de escribir una solución todo en uno lo mejor que pude con una pequeña modificación donde el usuario lo requiere.

Algunas notas importantes: simplemente cambie la variable recursivea FALSEsi solo desea que se procesen los archivos y carpetas de los directorios raíz. De lo contrario, pasa por todas las carpetas y archivos.

C&C muy bienvenido ...

@echo off
title %~nx0
chcp 65001 >NUL
set "dir=c:\users\%username%\desktop"
::
:: Recursive Loop routine - First Written by Ste on - 2020.01.24 - Rev 1
::
setlocal EnableDelayedExpansion
rem THIS IS A RECURSIVE SOLUTION [ALBEIT IF YOU CHANGE THE RECURSIVE TO FALSE, NO]
rem By removing the /s switch from the first loop if you want to loop through
rem the base folder only.
set recursive=TRUE
if %recursive% equ TRUE ( set recursive=/s ) else ( set recursive= )
endlocal & set recursive=%recursive%
cd /d %dir%
echo Directory %cd%
for %%F in ("*") do (echo    → %%F)                                 %= Loop through the current directory. =%
for /f "delims==" %%D in ('dir "%dir%" /ad /b %recursive%') do (    %= Loop through the sub-directories only if the recursive variable is TRUE. =%
  echo Directory %%D
  echo %recursive% | find "/s" >NUL 2>NUL && (
    pushd %%D
    cd /d %%D
    for /f "delims==" %%F in ('dir "*" /b') do (                      %= Then loop through each pushd' folder and work on the files and folders =%
      echo %%~aF | find /v "d" >NUL 2>NUL && (                        %= This will weed out the directories by checking their attributes for the lack of 'd' with the /v switch therefore you can now work on the files only. =%
      rem You can do stuff to your files here.
      rem Below are some examples of the info you can get by expanding the %%F variable.
      rem Uncomment one at a time to see the results.
      echo    → %%~F           &rem expands %%F removing any surrounding quotes (")
      rem echo    → %%~dF          &rem expands %%F to a drive letter only
      rem echo    → %%~fF          &rem expands %%F to a fully qualified path name
      rem echo    → %%~pF          &rem expands %%A to a path only
      rem echo    → %%~nF          &rem expands %%F to a file name only
      rem echo    → %%~xF          &rem expands %%F to a file extension only
      rem echo    → %%~sF          &rem expanded path contains short names only
      rem echo    → %%~aF          &rem expands %%F to file attributes of file
      rem echo    → %%~tF          &rem expands %%F to date/time of file
      rem echo    → %%~zF          &rem expands %%F to size of file
      rem echo    → %%~dpF         &rem expands %%F to a drive letter and path only
      rem echo    → %%~nxF         &rem expands %%F to a file name and extension only
      rem echo    → %%~fsF         &rem expands %%F to a full path name with short names only
      rem echo    → %%~dp$dir:F    &rem searches the directories listed in the 'dir' environment variable and expands %%F 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
      rem echo    → %%~ftzaF       &rem expands %%F to a DIR like output line
      )
      )
    popd
    )
  )
echo/ & pause & cls
Ste
fuente