web-dev-qa-db-ja.com

FORループ内のWindowsコマンドプロンプトで現在のディレクトリ名を取得するにはどうすればよいですか?

Win-1064ビットを使用しています。

私のWindowsマシンで次のディレクトリ構造を考えると...

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

...各ディレクトリ内のすべてのファイルの名前をディレクトリ名の前に付けて名前を変更しようとしています。

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

これを実現するために、FORを使用して%basedir%内のファイルを再帰的にループし、各ディレクトリで、内部のFOR「ループ」を使用して現在のディレクトリ名を取得し、名前を変更します。ただし、現在のディレクトリは通常正しく派生していません。問題を再現できる.batファイルは次のとおりです。

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

両方のファイルの%curdir%に同じ値を出力します。

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>

私は試した:

  1. 新鮮なコンソールウィンドウ
  2. コンソールとバッチファイル
  3. 最初のフォルダ名を取得することもあれば、2番目のフォルダ名を取得することもあります
  4. インターネットでたくさんの検索

追加のソフトウェアを持っていない可能性のある他のユーザーにスクリプトを配布する必要があるため、標準のWindowsユーティリティを使用することをお勧めします。

FORループ内のWindowsコマンドプロンプトで現在のディレクトリ名を取得するにはどうすればよいですか?

2
Mykola Novik

確かにDelayedExpansionが役に立ちました、DavidPostillに感謝します。作業スクリプトは次のとおりです。

@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
2
Mykola Novik
  • 1つのループで、質問と同じ結果を得るには、次のようにします。
@echo off

set "_=echo\ -------------------"
for /D /R "c:\tmp\Logs_UAT" %%I in (*
)do %_% & echo\%%~nxI & dir "%%~nxI" & echo\ %%~nxI & %_%
  • あなたの出力:
 -------------------

 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. 複数のforループを使用する必要はなく、すべてのサブディレクトリで再帰的に1つのループでfor /D /Rを使用します。これにより、DelayedExpansionは不要になります。

  2. temp.tempと追加のforループを使用して、ディレクトリ全体でファイルfor /Dを作成および削除する必要があるのはなぜですか?ループ内の現在のフォルダーの名前(すべてのsub/Rirectoriesで/Decursive)が変数%%~nxI(および他の多くの拡張可能なものも)に格納されている場合は、ループで使用するために、それらを使用してください...

    • 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.: directory nameでの%%~xの使用について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. DelayedExpansionを使用する必要はなく、cmd /v/c echo\!curdir!またはecho\%%~nxIを使用できます。

  4. コード出力の質問と同じように出力を取得するには、バナーの変数(set _=echo\ ----)を設定/使用し、これを目的のレイアウト出力に調整します。

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

    または、1つの従来のフォーマットで

    • @echo off
      
      set "_=echo\ -------------------"
      
      for /D /R "c:\tmp\Logs_UAT" %%I in (*)do (
      
      %_%
      echo\%%~nxI
      dir "%%~nxI"
      echo\ %%~nxI
      %_%
      
      )
  5. for /D /Rループを含む1行の1つの単純で短い出力オプションについては、次のことを試すことができます。

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

2
It Wasn't Me