Itérer tous les fichiers d'un répertoire à l'aide d'une boucle 'for'


353

Comment puis-je parcourir chaque fichier d'un répertoire à l'aide d'une forboucle?

Et comment savoir si une certaine entrée est un répertoire ou s'il s'agit simplement d'un fichier?


1
en supposant que vous vouliez dire le shell Windows par défaut, j'ai redéfini votre message pour un peu plus de clarté
David Schmitt

2
Veuillez également spécifier la version de Windows que vous utilisez.
JOP

1
Cela devrait être divisé en deux questions distinctes car elles sont indépendantes l'une de l'autre.
julealgon

Réponses:


493

Cela répertorie tous les fichiers (et seulement les fichiers) dans le répertoire actuel:

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

De plus, si vous exécutez cette commande dans un fichier de commandes, vous devez doubler les signes%.

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

(merci @agnul)


73
Si vous ne souhaitez pas l'utiliser de manière récursive, assurez-vous de retirer le / r
jocull

28
Si vous voulez faire l' écho que les noms de fichiers (pas le chemin complet) avec leurs extensions dans le répertoire courant (récursive), vous pouvez le faire comme ceci: for /r %i in (*) do ( echo %~nxi ). Ce fil peut aussi être très utile: stackoverflow.com/questions/112055/… .
Sk8erPeter

2
@Vaccano oui, après le Do, utilisez des parenthèses. C'est-à-dire (écho% i & del% i). Vous pouvez également utiliser "enter" au lieu de "&" pour plusieurs commandes.
Jay

2
Si vous utilisez des commandes telles que copier / déplacer plutôt que l'écho, assurez-vous de bien citer le chemin. for / r %% i in (*) do echo "%% i"
Soundararajan

2
Vous devez apparemment utiliser des noms de variables à une seule lettre.
Álvaro González

214

Itérer à travers ...

  • ... fichiers dans le répertoire courant: for %f in (.\*) do @echo %f
  • ... sous-répertoires dans le répertoire actuel: for /D %s in (.\*) do @echo %s
  • ... fichiers dans les sous-répertoires actuels et: for /R %f in (.\*) do @echo %f
  • ... sous-répertoires dans le courant et tous les sous-répertoires: for /R /D %s in (.\*) do @echo %s

Malheureusement, je n'ai trouvé aucun moyen de parcourir les fichiers et les sous-répertoires en même temps.

Utilisez simplement cygwin avec son bash pour plus de fonctionnalités.

En dehors de cela: avez-vous remarqué que l'aide à la compilation de MS Windows est une excellente ressource pour les descriptions de la syntaxe de la ligne de commande de cmd?

Jetez également un œil ici: http://technet.microsoft.com/en-us/library/bb490890.aspx


21
%fileet %subdirne peut contenir qu'un seul caractère, c'est %f-à- dire %s.
Felix Dombek

1
les «sous-répertoires du répertoire actuel» ne fonctionnent pas. Je reçois une erreur: s était inattendu pour le moment
Migrate2Lazarus voir mon profil le

78

Pour parcourir chaque fichier, une boucle for fonctionnera:

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

Dans mon cas, je voulais aussi le contenu du fichier, le nom, etc.

Cela a conduit à quelques problèmes et j'ai pensé que mon cas d'utilisation pourrait aider. Voici une boucle qui lit les informations de chaque fichier '.txt' dans un répertoire et vous permet de faire quelque chose avec (setx par exemple).

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

* Limitation: val <= %% f n'obtiendra que la première ligne du fichier.


18
Ah, un exemple multiligne. Merci pour ça!
Nyerguds

@Aaron Votre Comment terminer une boucle?
nijogeorgep

@nijogeorgep Vous n'avez pas à "terminer" la boucle. Dans mon exemple, tout ce qui se trouve entre parenthèses (echo, etc.) sera exécuté une fois pour chaque fichier '* .txt' du répertoire. Je pense que la réponse que vous cherchez pourrait être mieux expliquée ici: stackoverflow.com/questions/1355791/…
Aaron Votre

@Aaron Votre J'essayais d'exécuter des commandes maven en utilisant un script, mais il fonctionnait en boucle infinie, alors je l'ai demandé. Acheter maintenant J'ai ajouté une sortie à ma boucle et corrigé mon problème
nijogeorgep

@nijogeorgep Heureux que vous l'ayez compris!
Aaron Votre

57

Il existe une différence subtile entre l'exécution à FORpartir de la ligne de commande et à partir d'un fichier de commandes. Dans un fichier batch, vous devez mettre deux %caractères devant chaque référence de variable.

Depuis une ligne de commande:

FOR %i IN (*) DO ECHO %i

A partir d'un fichier batch:

FOR %%i IN (*) DO ECHO %%i

44

Cette boucle for répertorie tous les fichiers d'un répertoire.

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

"delims =" est utile pour afficher les noms de fichiers longs avec des espaces dedans ....

'/ b "affiche uniquement les noms, pas les dates de taille, etc.

Quelques choses à savoir sur l'argument dir's / a.

  • Toute utilisation de "/ a" listerait tout, y compris les attributs cachés et système.
  • "/ ad" n'afficherait que les sous-répertoires, y compris ceux cachés et ceux du système.
  • L'argument "/ ad" élimine le contenu avec l'attribut 'D'irectory.
  • "/ adhs" montrera tout, mais les entrées avec l'attribut S''Rem 'D'irectory,' H'idden '.

Si vous l'utilisez sur la ligne de commande, supprimez un "%".

J'espère que cela t'aides.


10

% 1 fait référence au premier argument passé et ne peut pas être utilisé dans un itérateur.

Essaye ça:

@echo off
for %%i in (*.*) do echo %%i

Tu as raison. J'ai essayé en mode immédiat de vérifier la syntaxe FOR et j'ai collé la ligne directement dans la réponse en oubliant les paramètres :-)
Axeman


4

Pour parcourir tous les fichiers et dossiers que vous pouvez utiliser

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

Pour parcourir tous les dossiers, mais pas les fichiers, vous pouvez utiliser

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

/sdonnera tous les résultats dans l'arborescence des répertoires en profondeur illimitée. Vous pouvez ignorer /ssi vous souhaitez parcourir le contenu de ce dossier et non son sous-dossier

Implémentation de la recherche dans l'itération

Pour parcourir un fichier et des dossiers nommés particuliers, vous pouvez rechercher le nom et parcourir en utilisant la boucle for

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

Pour parcourir les dossiers / répertoires nommés particuliers et non les fichiers , utilisez-les /ADdans la même commande

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

4

J'ai eu du mal à faire fonctionner la réponse de jop avec un chemin absolu jusqu'à ce que je trouve cette référence: https://ss64.com/nt/for_r.html

L'exemple suivant parcourt tous les fichiers d'un répertoire donné par le chemin absolu.

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

3

Le code suivant crée un fichier nommé "AllFilesInCurrentDirectorylist.txt" dans le répertoire actuel, qui contient la liste de tous les fichiers (fichiers uniquement) dans le répertoire actuel. Vérifiez-le

dir /b /a-d > AllFilesInCurrentDirectorylist.txt

3

Il pourrait également utiliser la commande forfiles :

forfiles /s 

et vérifiez également s'il s'agit d'un répertoire

forfiles /p c:\ /s /m *.* /c "cmd /c if @isdir==true echo @file is a directory"

@isdir==truedoit être@isdir==TRUE
psyklopz

2

J'utiliserais vbscript (Windows Scripting Host), car en lot, je suis sûr que vous ne pouvez pas dire qu'un nom est un fichier ou un répertoire.

En vbs, cela peut être quelque chose comme ceci:

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

Vérifiez FileSystemObject sur MSDN .


J'aurais utilisé Perl pour cela. Malheureusement, cela ne dépend pas de moi.
Vhaerun, le

Une vieille application? Des choses tristes.
Biri

Un développeur idiot a vu des fichiers batch et a pensé qu'ils étaient le remède à tous nos problèmes.
Vhaerun

1
@Vhaerun Un avantage de Windows Script Host (WSH) par rapport à Perl serait que WSH est préinstallé avec toutes les versions de Windows, alors que Perl devrait être installé séparément, ce qui peut ou non être une option réalisable dans tous les cas.
Parampreet Dhatt

2

J'utilise la commande xcopy avec l'option / L pour obtenir les noms de fichiers. Donc, si vous voulez obtenir un répertoire ou tous les fichiers du sous-répertoire, vous pouvez faire quelque chose comme ceci:

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

J'utilise simplement le c: \ comme destination car il existe toujours sur les systèmes Windows et il ne copie pas, donc cela n'a pas d'importance. si vous voulez aussi les sous-répertoires, utilisez l'option / s à la fin. Vous pouvez également utiliser les autres commutateurs de xcopy si vous en avez besoin pour d'autres raisons.


2

Essayez ceci pour tester si un fichier est un répertoire:

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

Cela vous dira seulement si un fichier n'est PAS un répertoire, ce qui sera également vrai si le fichier n'existe pas, alors assurez-vous de vérifier d'abord si vous en avez besoin. Les carets (^) sont utilisés pour échapper aux symboles de redirection et la sortie de la liste de fichiers est redirigée vers NUL pour l'empêcher d'être affichée, tandis que la sortie d'erreur de la liste DIR est redirigée vers la sortie afin que vous puissiez tester le message DIR "Fichier non trouvé" ".


2

essaye ça:

::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

il compte les fichiers .msi et .exe dans votre répertoire (et dans le sous-répertoire). Cela fait donc la différence entre les dossiers et les fichiers en tant qu'exécutables.

Ajoutez simplement une extension (.pptx .docx ..) si vous avez besoin de filtrer d'autres fichiers dans la boucle


1

Dans mon cas, j'ai dû supprimer tous les fichiers et dossiers sous un dossier temporaire. C'est ainsi que j'ai fini par le faire. J'ai dû exécuter deux boucles, une pour le fichier et une pour les dossiers. Si les fichiers ou les dossiers ont des espaces dans leurs noms, vous devez utiliser ""

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"
)

1

Voici mon go avec des commentaires dans le code.

Je suis juste en train de frôler les compétences de biatch alors pardonnez toutes les erreurs flagrantes.

J'ai essayé d'écrire une solution tout en un du mieux que je pouvais avec une petite modification là où l'utilisateur l'exige.

Quelques notes importantes: Changez simplement la variable recursiveen FALSEsi vous voulez seulement que les fichiers et dossiers des répertoires racine soient traités. Sinon, il passe par tous les dossiers et fichiers.

C&C est le bienvenu ...

@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
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.