2 votes

Comment obtenir le nom du répertoire courant dans une invite de commande Windows à l'intérieur de boucle for ?

J'utilise Win-10 64-bit.

Compte tenu de la structure de répertoire suivante sur ma machine Windows...

c:\tmp\Logs_UAT\
'-> folder1
|   '-> test.txt
'-> folder2
    '-> test.txt

...J'essaie de renommer tous les fichiers dans chaque répertoire en les préfixant avec le nom du répertoire, pour avoir :

c:\tmp\Logs_UAT\
'-> folder1
|   '-> folder1_test.txt
'-> folder2
    '-> folder2_test.txt

Pour ce faire, je fais une boucle récursive à travers les fichiers du répertoire %basedir% J'utilise FOR et dans chaque répertoire, j'obtiens le nom du répertoire actuel en utilisant la "boucle" FOR interne, puis je renomme le répertoire. Cependant, le répertoire courant n'est généralement pas dérivé correctement. Voici le fichier .bat qui permet de reproduire le problème :

@echo off

set basedir=c:\tmp\Logs_UAT

for /R %basedir% %%I in (*) DO (
cd %%~pI

for %%G in (.) do echo %%~nxG> temp.temp
set /P curdir=<temp.temp
del /f temp.temp

echo.
echo -------------------
echo %%I
dir
echo %curdir%
echo -------------------
)

Il produit la même valeur pour %curdir% pour les deux dossiers :

C:\tmp>test.bat

-------------------
c:\tmp\Logs_UAT\folder1\test.txt
 Datenträger in Laufwerk C: ist OSDisk
 Volumeseriennummer: D280-2DC0

 Verzeichnis von C:\tmp\Logs_UAT\folder1

06.05.2020  19:29    <DIR>          .
06.05.2020  19:29    <DIR>          ..
06.05.2020  19:02                 0 test.txt
               1 Datei(en),              0 Bytes
               2 Verzeichnis(se), 291.684.151.296 Bytes frei
folder2
-------------------
.
-------------------
c:\tmp\Logs_UAT\folder2\test.txt
 Datenträger in Laufwerk C: ist OSDisk
 Volumeseriennummer: D280-2DC0

 Verzeichnis von C:\tmp\Logs_UAT\folder2

06.05.2020  19:29    <DIR>          .
06.05.2020  19:29    <DIR>          ..
06.05.2020  19:02                 0 test.txt
               1 Datei(en),              0 Bytes
               2 Verzeichnis(se), 291.684.151.296 Bytes frei
folder2
-------------------

C:\tmp\Logs_UAT\folder2>

J'ai essayé :

  1. Fenêtre de console fraîche
  2. Console et fichier batch
  3. Je reçois parfois le premier nom de dossier et parfois le second.
  4. Nombreuses recherches sur l'internet

Je préférerais m'en tenir aux utilitaires Windows standard car je dois distribuer le script à d'autres utilisateurs qui n'ont peut-être pas le logiciel supplémentaire.

Comment obtenir le nom du répertoire courant dans une invite de commande Windows à l'intérieur de boucle for ?

2voto

Jeremy Points 826

En effet, DelayedExpansion a aidé, merci DavidPostill. Voici le script qui fonctionne :

@echo off
SETLOCAL EnableDelayedExpansion
set basedir=c:\tmp\Logs_UAT

for /R %basedir% %%I in (*) DO (
cd %%~pI

for %%G in (.) do echo %%~nxG> temp.temp
set /P curdir=<temp.temp
del /f temp.temp

echo !curdir!
)

endlocal

2voto

iTwasnTme Points 5586
  • Pour obtenir le même résultat que dans votre question, en une seule boucle :

    @echo off

    set "_=echo\ -------------------" for /D /R "c:\tmp\LogsUAT" %%I in (* )do %% & echo\%%~nxI & dir "%%~nxI" & echo\ %%~nxI & %_%

  • Votre résultat :


    Volume in drive C has no label. Volume Serial Number is 32E8-70C5

    Directory of c:\tmp\Logs_UAT\folder1

    05/06/2020 02:40 PM <DIR> . 05/06/2020 02:40 PM <DIR> .. 05/06/2020 02:41 PM 8 test.txt 1 File(s) 8 bytes 2 Dir(s) 3,128,999,936 bytes free folder1


    Volume in drive C has no label. Volume Serial Number is 32E8-70C5

    Directory of c:\tmp\Logs_UAT\folder2

    05/06/2020 02:47 PM <DIR> . 05/06/2020 02:47 PM <DIR> .. 05/06/2020 02:48 PM 7 folder2.txt 1 File(s) 7 bytes 2 Dir(s) 3,128,999,936 bytes free folder2


  1. Il n'est pas nécessaire d'utiliser plusieurs for utiliser for /D /R dans une boucle récursive dans tous les sous-répertoires. DelayedExpansion pas nécessaire

  2. Pourquoi créer et supprimer un fichier ? temp.temp dans l'ensemble du répertoire à l'aide de for /D avec toute autre information supplémentaire. for boucle ? Lorsque vous avez déjà le nom du dossier courant dans votre boucle ( /R écursive dans tous les sous /D ) stockés dans la variable %%~nxI (et bien d'autres encore), donc, pour les utiliser dans vos boucles, utilisez-les...

    • Use the FOR variable syntax replacement: %~pI - expands %I to a path only %~nI - expands %I to a file name only %~xI - expands %I to a file extension only

    • The modifiers can be combined to get compound results: %~pnI - expands %I to a path and file name only %~pnxI - expands %I to a path, file name and extension only

    • )do %% & echo\%%~nxI & dir "%%~nxI" & echo\ %%~nxI & %%

      Obs . : A propos de l'utilisation %%~x en directory nom observation note en ss64.com :

    • Full Stop Bug Although Win32 will not recognise any file or directory name that begins or ends with a '.' (period/full stop) it is possible to include a Full Stop in the middle of a directory name and this can cause issues with FOR /D.

    • Parameter expansion will treat a Full Stop as a file extension, so for a directory name like "Sample 2.6.4" the output of %%~nI will be truncated to "Sample 2.6" to return the whole folder name use %%I or %%~nxI

  3. Vous n'avez pas besoin d'utiliser DelayedExpansion vous pouvez utiliser cmd /v/c echo\!curdir! o echo\%%~nxI

  4. Pour obtenir une sortie identique à celle de votre code, vous pouvez définir/utiliser une variable pour votre bannière ( set _=echo\ ---- ), l'ajuster en fonction de la sortie de la mise en page souhaitée :

    • )do %% & echo\%%~nxI & dir "%%~nxI" & echo\ %%~nxI & %%

    Ou, dans un formatage conventionnel

    • @echo off

      set "_=echo\ -------------------"
      
      for /D /R "c:\tmp\Logs_UAT" %%I in (*)do (
      
      %_%
      echo\%%~nxI
      dir "%%~nxI"
      echo\ %%~nxI
      %_%
      
      )
  5. Pour une option de sortie simple et courte en une seule ligne avec for /D /R vous pouvez essayer :

    • @echo off

      for /d /r "c:\tmp\Logs_UAT" %%I in (*)do set "curdir=%%~nxI" && cmd /v /c " echo\!curdir!"

0voto

Lo Juego Points 567

Ma solution générale pour trouver tous les niveaux de répertoires :

@ECHO OFF
setlocal enabledelayedexpansion EnableExtensions

::Sample BAT to find all levels directories
:: FULL current path: "G:\First our directory\Second our directory\Third. - Strange . directory\Fourth and last  directory"

:: Get full current path (could be passed as a parameter to use as subroutine)
SET ActualP=%CD%
:: Set starting counter number
SET /A Countdir=0
:: Find number of directorie levels, echoes them to console and set associated variables
FOR %%G in ("%ActualP:\=" "%") DO (SET /A "CountDir+=1"
  set "Lvl=%%G"
  set "Lvl!Countdir!=!Lvl!"
  ECHO Lvl!Countdir!:!Lvl!
  )
ECHO.
:: Check number of levels to console
ECHO Levels of directorie: %CountDir%
ECHO.
:: Get last (current) level of directory free of double quotes and echoes it to console 
:: between brackets to assure not extra chars are present
SET "LastLvl=%Lvl:"=%"
ECHO LastLvl: [%LastLvl%]
:: Just to be sure that the variables have been set:
ECHO.
ECHO Third level of directorie: %Lvl3%
PAUSE
EXIT

:: This wiil echoes to console:
::   
::   Lvl1:"G:"
::   Lvl2:"First our directory"
::   Lvl3:"Second our directory"
::   Lvl4:"Third. - Strange . directory"
::   Lvl5:"Fourth and last  directory"
::   
::   Levels of directorie: 5
::   
::   LastLvl: [Fourth and last  directory]
::   
::   Third level of directorie: "Second our directory"
::   Premere un tasto per continuare . . .

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X