我正在使用 Win-10 64 位。
鉴于我的 Windows 机器上的以下目录结构...
c:\tmp\Logs_UAT\
'-> folder1
| '-> test.txt
'-> folder2
'-> test.txt
...我尝试通过在目录名称前加上前缀来重命名每个目录中的所有文件,如下所示:
c:\tmp\Logs_UAT\
'-> folder1
| '-> folder1_test.txt
'-> folder2
'-> folder2_test.txt
为了实现这一点,我%basedir%
使用 FOR 递归循环遍历文件,并在每个目录中使用内部 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>
我试过:
- 新鲜的控制台窗口
- 控制台和批处理文件
- 有时我会得到第一个文件夹名称,有时我会得到第二个
- 在网上搜索了很多
我宁愿坚持使用标准的 Windows 实用程序,因为我必须将脚本分发给可能没有额外软件的其他用户。
如何在 FOR 循环内的 Windows 命令提示符中获取当前目录名称?
答案1
确实,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
- 为了让您在一次循环中获得与问题相同的结果:
@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
-------------------
您不需要使用多个
for
循环,for /D /R
只需在所有子目录中使用一个循环递归即可,这样就DelayedExpansion
没有必要FOR /R - Loop through files (recursively) FOR /D - Loop through several folders/directories
The option /D /r is undocumented, but can be a useful combination, while it will recurse through all subfolders the wildcard will only match against Folder/Directory names (not filenames) Note: Source linked to ss64.com
Rem :: Set your folder /Directory /Recursively tree starting at "c:\tmp\Logs_UAT" For /D /R "c:\tmp\Logs_UAT"
为什么需要使用任何附加循环
temp.temp
在整个目录中创建和删除文件?当您已经在循环中将当前文件夹的名称(在所有子目录中递归)存储在变量中(并且还有许多其他可用的变量)时,因此,要在循环中使用,只需使用它们即可……for /D
for
/R
/D
%%~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 & %_%
观察.: 关于使用
%%~x
在directory
名称观察注释中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
您不需要使用
DelayedExpansion
,您可以使用cmd /v/c echo\!curdir!
或echo\%%~nxI
By default expansion will happen just once, before each line is executed. The !delayed! expansion is performed each time the line is executed, or for each loop in a FOR looping command. Note: Source linked to ss64.com
这正是您的代码在您的问题(和答案)中所做的事情,您使用了多个
for
循环,而DelayedExpansion
如果您使用单个循环,则没有必要for /D /R
使用时%%~nxI
对于相同的结果并在选定的行上使用,如果您使用一个或多个
for
循环,您还可以DelayedExpansion
在运行时使用cmd /v /c echo\!curdir!
扩展当时的变量值来启用。)do set "curdir=%%~nxI" && cmd /v /c " echo\!curdir!"
为了获得与代码输出问题相同的输出,您可以为横幅设置/使用一个变量(
set _=echo\ ----
),并将其调整为所需的布局输出:)do %_% & echo\%%~nxI & dir "%%~nxI" & echo\ %%~nxI & %_%
或者,按照一种常规格式
@echo off set "_=echo\ -------------------" for /D /R "c:\tmp\Logs_UAT" %%I in (*)do ( %_% echo\%%~nxI dir "%%~nxI" echo\ %%~nxI %_% )
对于一行中带有
for /D /R
循环的一个简单而简短的输出选项,您可以尝试:@echo off for /d /r "c:\tmp\Logs_UAT" %%I in (*)do set "curdir=%%~nxI" && cmd /v /c " echo\!curdir!"
答案3
我查找各级目录的一般解决方案是:
@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 . . .