web-dev-qa-db-fra.com

Fichiers batch: Répertorie tous les fichiers d'un répertoire avec des chemins relatifs

Concernant les fichiers batch Windows: Existe-t-il un moyen de répertorier tous les fichiers (ou tous d'un type spécifique) d'un répertoire donné et de ses sous-répertoires, y compris les chemins relatifs au répertoire actuel (ou de recherche) de la liste?

Par exemple, si je veux tous les fichiers .txt du répertoire et des sous-répertoires actuels avec leurs chemins d'accès complets, je peux le faire.

for /r . %%g in (*.txt) do echo %%g >> C:\temp\test.txt

ou

dir *.txt /b /s >> C:\temp\test.txt

et je vais obtenir quelque chose comme

C:\test\Doc1.txt
C:\test\subdir\Doc2.txt
C:\test\subdir\Doc3.txt

Si je fais

for /r . %%g in (*.txt) do echo %%~nxg >> C:\temp\test.txt

Je vais avoir quelque chose comme

Doc1.txt
Doc2.txt
Doc3.txt

Mais ce que je veux vraiment, c'est:

Doc1.txt
subdir\Doc2.txt
subdir\Doc3.txt

C'est possible?

Si mon message est trop déroutant: je veux fondamentalement liste récursivement les fichiers dans Linux CLI avec chemin relatif au répertoire en cours, mais juste pour Windows.

59
Tim Meyer

Vous pouvez simplement obtenir la longueur de caractères du répertoire courant et les supprimer de votre liste absolue

setlocal EnableDelayedExpansion
for /L %%n in (1 1 500) do if "!__cd__:~%%n,1!" neq "" set /a "len=%%n+1"
setlocal DisableDelayedExpansion
for /r . %%g in (*.log) do (
  set "absPath=%%g"
  setlocal EnableDelayedExpansion
  set "relPath=!absPath:~%len%!"
  echo(!relPath!
  endlocal
)
23
jeb

Le moyen le plus simple (mais pas le plus rapide) de parcourir une arborescence de répertoires et de répertorier les chemins de fichiers relatifs consiste à utiliser FORFILES .

forfiles /s /m *.txt /c "cmd /c echo @relpath"

Les chemins relatifs seront cités avec un .\ un péché

".\Doc1.txt"
".\subdir\Doc2.txt"
".\subdir\Doc3.txt"


Pour supprimer les guillemets:

for /f %%A in ('forfiles /s /m *.txt /c "cmd /c echo @relpath"') do echo %%~A


Pour supprimer les guillemets et le .\:

setlocal disableDelayedExpansion
for /f "delims=" %%A in ('forfiles /s /m *.txt /c "cmd /c echo @relpath"') do (
  set "file=%%~A"
  setlocal enableDelayedExpansion
  echo !file:~2!
  endlocal
)

ou sans utiliser l'expansion retardée

for /f "tokens=1* delims=\" %%A in (
  'forfiles /s /m *.txt /c "cmd /c echo @relpath"'
) do for %%F in (^"%%B) do echo %%~F
34
dbenham

Cette réponse ne fonctionnera pas correctement avec des chemins racine contenant des signes égaux (=). (Merci @dbenham pour l'avoir signalé.)


EDITED: Correction du problème avec les chemins contenant !, encore repéré par @dbenham (merci!).

Au lieu de calculer la longueur et d’extraire les sous-chaînes, vous pouvez utiliser une approche différente:

  • stocker le chemin racine;

  • effacez le chemin racine des chemins de fichiers.

Voici ma tentative (qui a fonctionné pour moi):

@ECHO OFF
SETLOCAL DisableDelayedExpansion
SET "r=%__CD__%"
FOR /R . %%F IN (*) DO (
  SET "p=%%F"
  SETLOCAL EnableDelayedExpansion
  ECHO(!p:%r%=!
  ENDLOCAL
)

La variable r est affectée au répertoire actuel. À moins que le répertoire en cours soit le répertoire racine d'un lecteur de disque, il ne se terminera pas par \, que nous modifions en ajoutant le caractère.  (Ce n'est plus le cas, car le script lit maintenant le __CD__ variable, dont la valeur se termine toujours par \ _ (merci @jeb!), au lieu de CD.)

Dans la boucle, nous stockons le chemin du fichier actuel dans une variable. Ensuite, nous produisons la variable, en supprimant le chemin racine.

9
Andriy M

Bien sûr, vous pouvez écrire un algorithme récursif dans Batch qui vous permet de contrôler exactement ce que vous faites dans chaque sous-répertoire imbriqué:

@echo off
set mypath=
call :treeProcess
goto :eof

:treeProcess
setlocal
for %%f in (*.txt) do echo %mypath%%%f
for /D %%d in (*) do (
    set mypath=%mypath%%%d\
    cd %%d
    call :treeProcess
    cd ..
)
endlocal
exit /b
5
Aacini
@echo on>out.txt
@echo off
setlocal enabledelayedexpansion
set "parentfolder=%CD%"
for /r . %%g in (*.*) do (
  set "var=%%g"
  set var=!var:%parentfolder%=!
  echo !var! >> out.txt
)
3
Kedar