Situation:
I have many folders which are named like an email-address, eg username@domain.tld. These folders has to be renamed into just the username. so all characters until the "@" is my given string. (without the "@")
Current foldernames:
Requested foldernames:
Problem:
Thank you for every help!
@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
You might be able to do it with a one-liner (UNTESTED):
for /f "delims=@ tokens=1*" %a in ('dir /s /ad /b *@*') do @echo ren %a@%b %~nxa
How it works:
The dir /b /ad /s *@*
command produces a bare listing of full pathnames for all folders containing a @.
The delims=@
option splits each line into two: the first part before the @, and the second part after the @.
The ren
command renames the full pathname to the part before the @. The %~nxa
just extracts the name (and any extension) from the full path.
The echo
command is there, just so you can see what it's going to do. Once you're satisfied it will do the right thing, remove it.
NB
If you run this from a batch file, instead of interactively, use %%
instead of %
.
findstr
returns the entire line if it contains a match, not the matching part only, so you need to split off the @
character and everything after programmatically.
You do not need to use pushd
and popd
within a setlocal
/ endlocal
block because, the latter localises the current working directory too.
Avoid wrong-label remarks like ::
within blocks ()
of code, because they may cause trouble!
The following code does what you want:
@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
What happens:
cd
replaces pushd
/ popd
as setlocal
/ endlocal
suffices as aforementioned; findstr
is used to return only directory whose names start with a letter, followed by any number of characters not containing @
, followed by the @
character, followed by at least one character other than @
; :LEN
is called to determine the length (number of characters) of the current directory name, the result is stored in variable ILEN
; @
is removed from the directory name (by substring replacement syntax), the result is held by variable RIGHT
; :LEN
is called to determine the length of the string in RIGHT
, the result is given to variable RLEN
; 1
is calculated by set /A
, the result is used for getting the string portion before the @
symbol (by substring expansion syntax); The code looks a bit complicated, especially because of toggling delayed expansion, computing string lengths rather than using intelligent substring replacement syntax and passing variable names rather than string values to the subroutine. However, all this has been done to avoid trouble with directory names which contain special characters like !
, %
, =
, etc.
The great advantace of this approach is that it works even for symbols that consist of more than just a single character (supposing the dir
and findstr
patterns are adapted accordingly).
If it is guaranteed that the characters ^
and %
cannot occur in the directory names, the following code works fine and is a bit simpler ( "
would also be a harmful character but this is prohibited for file/dir. names anyway):
@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
The core function is the substring replacement hack set "LEFT=%LEFT:@=" & rem "%"
in the subroutine :SUB
, which removes the @
sign and everything after. Credits for this method go to Aacini -- see this post .
For the sake of completeness, here is a simple solution that works only if the symbol consists of a single character ( @
):
@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
It is an improved variant of Klitos Kyriacou's approach .
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.