我有一个脚本,可以从锚点位置(C:\ Temp \ Corporate Services)处理文件夹结构。对于树中的每个文件夹,如果路径包含单词Registers,那么我需要将寄存器下面的所有子文件夹作为前缀(Reg)。 以下是树的示例 - 有400家公司具有相同的文件夹结构如下:
> tree
C:.
└───Temp
└───Corporate Services
├───Company A
│ ├───Agreements
│ │ ├───2017
│ │ └───2018
│ └───Registers
│ ├───2016
│ ├───2017
│ └───2018
│ └───Folder1
│ └───Folder2
└───Company B
│ ├───Agreements
│ │ ├───2017
│ │ └───2018
│ └───Registers
│ ├───2016
│ ├───2017
│ └───2018
│ └───FolderX
│ └───Folder Y
└───Company C...
因此,如果完整路径为C:\ Temp \ Corporate Services \ Registers \ 2016,则需要将2016文件夹重命名为(REG)2017。 2017年和2018年相同。编辑:树可以延伸到年份文件夹以外的其他子文件夹,因此也需要重命名。
我已经设法通过树递归了但是在分析'registers'字符串的路径时卡住了。任何帮助将非常感激。
@echo off
set /A o=0
echo o starts as %o%
call :treeProcess
rem goto:eof
:treeProcess
setlocal enabledelayedexpansion
set /A i=1
REM echo i is %i%
for /f "tokens=*" %%f in ('dir /ad /s /b "C:\Temp\Corporate Services"') do (
echo root: %%f
for /D %%d in (*) do (
cd %%d
Set str1=%%~f
Set var=%str1:registers=%
echo %var%
REM if not "%var%"==%str1% echo found reg
set /A o=%i%+1
if %o%==2 goto :eof
if %o%==1 call :treeProcess
cd ..
)
ENDLOCAL
)
:eof
exit /b 0
答案 0 :(得分:1)
Dir /B/S/AD
从给定路径开始并递归搜索最后一个元素 - 因此只能有效地返回匹配的文件夹for /d
枚举文件夹的起点。(REG)
的文件夹。%%
%
时,可以在cmd行中执行
:: Q:\Test\2018\06\15\SO_50868596.cmd
@Echo off
set "SearchDir=C:\Temp\Corporate Services\Registers"
For /f "Delims=" %%A in ('Dir /B/S /AD "%SearchDir%"') Do For /D %%B in ("%%A\*"
) Do Echo=%%~nxB|findstr /i "^(REG)" 2>&1>NUL || Ren "%%~fB" "(REG)%%~nxB"
示例树输出:
> tree
C:.
└───Temp
└───Corporate Services
├───Company A
│ ├───Agreements
│ │ ├───2017
│ │ └───2018
│ └───Registers
│ ├───(REG)201
│ ├───(REG)201
│ └───(REG)201
└───Company B
答案 1 :(得分:0)
@ECHO OFF
SETLOCAL
SET "sourcedir=U:\sourcedir"
FOR /f "delims=" %%a IN (
'dir /b /s /ad "%sourcedir%\*" '
) DO (
FOR /L %%y IN (2016,1,2018) DO (
IF "%%~na" == "%%y" FOR %%p IN ("%%~dpa.") DO IF /i "%%~np"=="Registers" ECHO(REN "%%a" "(REG)%%y"
)
)
)
GOTO :EOF
您需要更改sourcedir
的设置以适合您的具体情况。
为了测试目的,所需的REN命令仅为ECHO
。 在您确认命令正确后,将ECHO(REN
更改为REN
以实际重命名文件。
首先,执行目录扫描,对于找到的每个目录,检查“名称”部分(%%~na
)是否为目标年份%%y
之一。
如果是,则如果父目录的名称部分是“注册”,则重命名。
哦 - 顺便说一句 - 在::-Comments
(括号内的行序列)中使用code block
不是一个好主意,因为::
是一个可以打破阻塞的标签。在REM
中使用code blocks
。
哦 - 刚刚意识到你想要重命名所有子目录,而不仅仅是2016..2018
。
更简单的代码:
@ECHO OFF
SETLOCAL
SET "sourcedir=U:\sourcedir"
FOR /f "delims=" %%a IN (
'dir /b /s /ad "%sourcedir%\*" '
) DO (
FOR %%p IN ("%%~dpa.") DO IF /i "%%~np"=="Registers" ECHO(REN "%%a" "(REG)%%~na"
)
)
GOTO :EOF
答案 2 :(得分:0)
你的代码有几个缺陷;其中一些是:
str1
,var
,o
)中的变量,这需要delayed expansion; /R
的开关dir
完全不需要(我猜你对备用数据流不感兴趣); :treeProcess
(自己调用它),这可能在某些情况下有效,但在这里不行,因为你已经递归地枚举了所有(子)目录({ {1}})无论如何;递归调用非常危险,例如,您可能很容易达到嵌套限制; dir /S
- 样式的注释,因为它们可能会导致意外的结果; ::
,应该是call :EOF
; goto :EOF
比较,因此它永远不会成为现实; 无论如何,由于您只想重命名某个层次结构级别的目录,我建议不要使用递归以避免意外更改。相反,我只会处理专用的子目录中的目录:
if
要处理曾祖母的子目录,您可以使用以下代码:
@echo off
setlocal EnableExtensions DisableDelayedExpansion
rem // Define constants here:
set "_ROOT=C:\Temp\Corporate Services"
set "_NAME=Registers"
set "_PREF=(REG)"
rem // Enumerate immediate child directories of root directory:
for /D %%A in ("%_ROOT%\*") do (
rem // Try to change into certain grand-child directory:
2> nul pushd "%%~A\%_NAME%" && (
rem // Enumerate grand-grand-child directories and filter them:
for /F "delims=" %%C in ('
2^> nul dir /B /A:D "*" ^| findstr /I /V /B /C:"%_PREF%"
') do (
rem // Rename directories that have not yet been:
ECHO ren "%%~C" "%_PREF%%%~C"
)
rem // Return from grand-child directory:
popd
)
)
endlocal
exit /B