[英]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.