[英]Windows batch file and regex: rename all folders without given string
情况:
我有许多文件夹,其名称类似于电子邮件地址,例如username@domain.tld。 必须将这些文件夹重命名为用户名。 所以直到“@”的所有字符都是我给定的字符串。 (没有“@”)
目前的文字名称:
请求的foldernames:
问题:
谢谢你的帮助!
@ECHO off
SETLOCAL ENABLEDELAYEDEXPANSION
SET pathMail="C:\Users\Username\Desktop\Batchtest\Folderstructure"
PUSHD %pathMail%
ECHO "::Extract string from folder"
FOR /f %%G in ('DIR /b /ad ^| FINDSTR /r "[a-z].*[^@]"') DO (
::wrong logic!?
REN %%G=%%G
)
POPD
:EOF
您可以使用单行(UNTESTED)来执行此操作:
for /f "delims=@ tokens=1*" %a in ('dir /s /ad /b *@*') do @echo ren %a@%b %~nxa
这个怎么运作:
dir /b /ad /s *@*
命令为包含@的所有文件夹生成一个完整路径名的裸列表。
delims=@
选项将每一行分成两行:@之前的第一部分和@之后的第二部分。
ren
命令将完整路径名重命名为@之前的部分。 %~nxa
只从完整路径中提取名称(和任何扩展名)。
echo
命令就在那里,这样你就可以看到它将要做什么。 一旦你满意,它会做正确的事情,删除它。
NB
如果从批处理文件中运行此操作,而不是以交互方式运行,请使用%%
而不是%
。
findstr
返回整行,如果它包含匹配,而不是匹配的部分,所以你需要在编程后拆分@
字符和所有内容。
您不需要在setlocal
/ endlocal
块中使用pushd
和popd
,因为后者也会对当前工作目录进行本地化。
避免使用像::
block ()
代码中的错误标签备注,因为它们可能会造成麻烦!
以下代码执行您想要的操作:
@echo off
setlocal EnableExtensions DisableDelayedExpansion
set "pathMail=C:\Users\Username\Desktop\Batchtest\Folderstructure"
cd /D "%pathMail%"
for /F %%G in ('
dir /B /A:D "?*@*" ^| findstr /I /R "^[a-z][^@]*@[^@][^@]*$"
') do (
set "ITEM=%%G"
setlocal EnableDelayedExpansion
call :LEN ILEN ITEM
set "RIGHT=!ITEM:*@=!"
call :LEN RLEN RIGHT
for /F "delims=" %%N in ('set /A "ILEN-=!RLEN!+1"') do (
rem Remove `ECHO` to actually rename any directories:
ECHO ren "%%G" "!ITEM:~,%%N!"
)
endlocal
)
endlocal
exit /B
:LEN output input
setlocal EnableDelayedExpansion
set /A "SLEN=0"
if "%~2"=="" goto :END
set "STRING=!%~2!"
if not defined STRING goto :END
set /A "SLEN=1"
for %%I in (4096 2048 1024 512 256 128 64 32 16 8 4 2 1) do (
if not "!STRING:~%%I!"=="" (
set /A "SLEN+=%%I"
set "STRING=!STRING:~%%I!"
)
)
:END
if "%~1"=="" (
echo(%SLEN%
endlocal
) else (
endlocal & set "%~1=%SLEN%"
)
exit /B
怎么了:
cd
将pushd
/ popd
替换为setlocal
/ endlocal
就足够了; findstr
用于仅返回名称以字母开头的目录,后跟任意数量的不包含@
的字符,后跟@
字符,后跟至少一个除@
以外的字符; :LEN
调用:LEN
来确定当前目录名的长度(字符数),结果存储在变量ILEN
; @
所有内容(通过子字符串替换语法),结果由变量RIGHT
; :LEN
调用:LEN
来确定RIGHT
字符串的长度,结果赋予变量RLEN
; 1
之间的差值由set /A
计算,结果用于获取@
符号之前的字符串部分(通过子字符串扩展语法); 代码看起来有点复杂,特别是因为切换延迟扩展,计算字符串长度而不是使用智能子字符串替换语法并将变量名称而不是字符串值传递给子例程。 但是,所有这些都是为了避免使用包含特殊字符的目录名称的麻烦!
, %
, =
等
这种方法的巨大优势在于它甚至可以用于由不止一个字符组成的符号(假设dir
和findstr
模式相应地进行了调整)。
如果保证在目录名中不能出现字符^
和%
,则以下代码可以正常工作并且更简单一些( "
也可能是有害字符,但无论如何都禁止使用file / dir。”):
@echo off
setlocal EnableExtensions DisableDelayedExpansion
set "pathMail=C:\Users\Username\Desktop\Batchtest\Folderstructure"
cd /D "%pathMail%"
for /F %%G in ('
dir /B /A:D "?*@*" ^| findstr /I /R "^[a-z][^@]*@[^@][^@]*$"
') do (
call :SUB ITEM "%%G"
rem Remove `ECHO` to actually rename any directories:
call ECHO ren "%%G" "%%ITEM%%"
)
endlocal
exit /B
:SUB output %input%
set "LEFT=%~2"
if not defined LEFT goto :EOF
set "LEFT=%LEFT:@=" & rem "%"
if "%~1"=="" (
echo "%LEFT%"
) else (
set "%~1=%LEFT%"
)
goto :EOF
核心函数是子程序中的子串替换黑客set "LEFT=%LEFT:@=" & rem "%"
:SUB
,它删除了@
符号及其后的所有内容。 这种方法的积分转到Aacini - 请看这篇文章 。
为了完整起见,这是一个简单的解决方案,仅当符号由单个字符( @
)组成时才有效:
@echo off
setlocal EnableExtensions DisableDelayedExpansion
set "pathMail=C:\Users\Username\Desktop\Batchtest\Folderstructure"
cd /D "%pathMail%"
for /F "eol=| delims=" %%G in ('
dir /B /A:D "?*@*" ^| findstr /I /R "^[a-z][^@]*@[^@][^@]*$"
') do (
for /F "eol=| delims=@" %%N in ("%%G") do (
rem Remove `ECHO` to actually rename any directories:
ECHO ren "%%G" "%%N"
)
)
endlocal
exit /B
它是Klitos Kyriacou方法的改进版本。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.