How to find and replace part of filenames from list - batch-file

I have a list of files that I need to rename at the same part of each file, with different values.
Example:
BL_1402B103_abc.wav > BL_C1234-1_abc.wav
BL_15489B59_abc.wav > BL_C1234-5_abc.wav
So in the first example above I want to replace the 1402B103 with C1234-1 all the files are the same length and the sections I want to replace are separated by "_".
I have some code for finding/replacing parts of a filename but I need to do this for hundreds of files - is there a way to pull Pattern= & Replace= as variables from a csv/list and run as a batch?
Setlocal enabledelayedexpansion
Set "Pattern=1402B103"
Set "Replace=C1234-1"
For %%f in (*.wav) Do (
Set "File=%%~f"
Ren "%%f" "!File:%Pattern%=%Replace%!"
)

You could create a csv file and add your search/replace strings:
myfile.csv
1402B103,C1234-1
15489B59,C1234-5
etc,etc
The batch file, myrename.cmd
#echo off
setlocal enabledelayedexpansion
for /f "tokens=1,* delims=," %%i in (myfile.csv) do (
set "search=%%i"
set "replace=%%j"
call :fix
)
exit /b
:fix
for %%a in (*!search!*.wav) do (
set "file=%%a"
set "file=!file:%search%=%replace%!!"
echo ren "%%~fa" "!file!"
)
It will seatch for each string in the csv file, split by comma assign the first meta variable to the search variable and the second to the replace variable. Then we simply do the replace for each by calling that procedure.
Note!! in this instance I used echo before ren for testing results. Only once you are happy with your results should you remove echo to perform the actual command.

I would do such a multi-rename operation of files using shareware Total Commander with its built-in multi-rename tool which has a every easy to use graphical user interface for such tasks making it possible to review the new names of the files before executing the rename operation. This file rename operation could be done with Total Commander nearly complete using only some mouse clicks, just C1234- need to be typed on keyboard. And Total Commander supports even an undo if the rename operation fails for some reason.
Let us assume C1234- in new file name is a fixed sequence of characters and 1 and 5 is a number incremented by one on each renamed each file.
#echo off
setlocal EnableExtensions EnableDelayedExpansion
set "FileNumber=1"
for /F "eol=| delims=" %%I in ('dir BL_????????_abc.wav /A-D-H /B /ON 2^>nul') do (
move /Y "%%I" "BL_C1234-!FileNumber!_abc%%~xI" >nul
set /A FileNumber+=1
)
endlocal
This solution works for the example.
But what about string left to first underscore and string right to second underscore vary from file name to file name?
In this case the following batch file could be the right solution:
#echo off
setlocal EnableExtensions EnableDelayedExpansion
set "FileNumber=1"
for /F "eol=| delims=" %%I in ('dir *_????????_*.wav /A-D-H /B /ON 2^>nul') do (
for /F "eol=| tokens=1,2* delims=_" %%A in ("%%~nxI") do (
move /Y "%%I" "%%A_C1234-!FileNumber!_%%C" >nul
)
set /A FileNumber+=1
)
endlocal
The command MOVE with option /Y is used instead of command REN to make the file rename even on a file with that name is already existing. Total Commander would inform the user about such an issue on renaming files with other files with new name already existing.
For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.
dir /?
echo /?
endlocal /?
for /?
move /?
set /?
setlocal /?
Read the Microsoft article about Using Command Redirection Operators for an explanation of 2>nul. The redirection operator > must be escaped with caret character ^ on FOR command line to be interpreted as literal character when Windows command interpreter processes this command line before executing command FOR which executes the embedded dir command line with using a separate command process started in background.

Batch solutions just make it hard to know what to do.
Batch is far too unreadable for my liking. %% and ! and !! in weird places. Bah.
You are better off making a C# console app that gives you 2 prompts and just does it, like I did.
In any case, what is being demonstrated is, for each file, you grab that filename as a string variable, and do all the string replacements in that string variable. Then you rename the file, or in C# it's MoveTo(newPath), the resulting string variable.

Related

Filename editing with batch

So I'm working on a script for file renaming/editing and I'm getting an error
The system cannot find the file specified
I'm assuming it's because of the loop, how can I fix this
#echo off
Setlocal enabledelayedexpansion
cd /d "%~dp0"
for /f "delims=*" %%a IN ('dir /b /s /a-d "Folder1\(*)*.txt"') DO (
Set "File=%%~nxa"
Ren "%%a" "!File:(1)=(-125)!"
Ren "%%a" "!File:(2)=(-124)!"
Ren "%%a" "!File:(3)=(-121)!"
Ren "%%a" "!File:(4)=(-117)!"
Ren "%%a" "!File:(5)=(-120)!"
Ren "%%a" "!File:(6)=(-116)!"
Ren "%%a" "!File:(7)=(-115)!"
Ren "%%a" "!File:(8)=(-127)!"
Ren "%%a" "!File:(9)=(-126)!"
Ren "%%a" "!File:(10)=(-100)!"
)
Source Folder1
(1) filename.txt
(2) filename.txt
(3) filename.txt
Source Folder1 Results
(-125) filename.txt
(-124) filename.txt
(-121) filename.txt
As you can see the script does work, but I am getting the message
I also tested it with this for /f "Tokens=*" same results
There can be used the following code for this task.
#echo off
setlocal EnableExtensions DisableDelayedExpansion
pushd "%~dp0Folder1" || exit /B
for /F "delims=" %%I in ('dir "(*)*.txt" /A-D-L /B 2^>nul') do (
set "FileName=%%I"
setlocal EnableDelayedExpansion
set "NewName=!FileName:(1)=(-125)!"
set "NewName=!NewName:(2)=(-124)!"
set "NewName=!NewName:(3)=(-121)!"
set "NewName=!NewName:(4)=(-117)!"
set "NewName=!NewName:(5)=(-120)!"
set "NewName=!NewName:(6)=(-116)!"
set "NewName=!NewName:(7)=(-115)!"
set "NewName=!NewName:(8)=(-127)!"
set "NewName=!NewName:(9)=(-126)!"
set "NewName=!NewName:(10)=(-100)!"
ren "!FileName!" "!NewName!"
endlocal
)
popd
endlocal
There is first defined the required execution environment with
command echo mode turned off and
command extensions enabled and
delayed variable expansion disabled.
Next the subdirectory Folder1 of the batch file directory is made the current working directory or the batch file processing is exited if that folder does not exist at all.
Then one more Windows command process is started in background with %ComSpec% /c and the command line within ' of command FOR appended as additional arguments. There is executed with Windows installed into C:\Windows:
C:\Windows\System32\cmd.exe /c dir "(*)*.txt" /A-D-L /B 2>nul
The command DIR searches
in the current directory
for just files because of /A-D-L (attribute not directory and not link (reparse point))
with a file name matched by the wildcard pattern (*)*.txt and
outputs just the matching names without path in bare format because of /B.
It is possible that DIR does not find a matching file name in which case an error message is output which is suppressed by redirecting it from STDERR (standard error) to device NUL.
Read the Microsoft documentation about Using command redirection operators for an explanation of 2>nul. The redirection operator > must be escaped with caret character ^ on FOR command line to be interpreted as literal character when Windows command interpreter processes this command line before executing command FOR which executes the embedded dir command line with using a separate command process started in background.
FOR with option /F captures all output to STDOUT (standard output) of started cmd.exe and waits for self-termination of started cmd.exe before the captured output is processed line by line.
Empty lines are ignored which do not exist here at all. There would be split up by default the file names into substrings using normal space and horizontal tab as string delimiters, analyzed if the first substring begins with a semicolon in which case the line (file name) would be also ignored while otherwise the first space/tab delimited substring is assigned to the specified loop variable I before running the commands in body of FOR.
The line (file name) splitting behavior is not wanted which is the reason for usage of the option delims= to define an empty list of string delimiters to turn off the line splitting into substrings. The default end of line character ; can be kept in this case as all file names to process start definitely with character (.
The file name without path is first assigned to the environment variable FileName which works also for file names containing one or more exclamation marks as delayed variable expansion is disabled at execution of this command line.
Next is enabled delayed variable expansion as required for the next commands. Please read this answer for details about the commands SETLOCAL and ENDLOCAL and what really happens in memory of running cmd process on using these two commands.
A series of string substitutions is done next with command SET to define the new file name based on the current file name before running just once the command REN to rename the current file to the new name.
The code posted in the question tries to rename the file multiple times. It fails on string substitution does not change anything at all because of a file cannot be renamed on new name being equal the current name. Then one REN command works on which the string substitution was successful. The other REN command fail again because of the file is already renamed and renaming it once again with original file name cannot work anymore for that reason.
The initial environment with disabled delayed variable expansion is restored last before processing the next file name.
There could be used for this task also:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
pushd "%~dp0Folder1" || exit /B
for %%# in ("1 125" "2 124" "3 121" "4 117" "5 120" "6 116" "7 115" "8 127" "9 126" "10 100") do for /F "tokens=1,2" %%G in (%%#) do for %%I in ("(%%G)*.txt") do for /F "tokens=1* delims=)" %%J in ("%%I") do ren "%%I" "(-%%H)%%K"
popd
endlocal
For each pair of current and new number a string splitting is done to assign the current number to the loop variable G and the new number to the loop variable H before a FOR is used to process all files with current number (G) of which file name is assigned to loop variable I which is split up on first occurrence of a closing round bracket to get the part after first ) from entire file name with file extension assigned to the loop variable K to be able to rename the file with the new number.
There are several other solutions possible too.
To understand the commands used and how they work, open a command prompt window, execute there the following commands, and read the displayed help pages for each command, entirely and carefully.
call /? ... explains %~dp0 ... drive and path of argument 0 which is the batch file path always ending with a backslash.
dir /?
echo /?
endlocal /?
exit /?
for /?
popd /?
pushd /?
ren /?
set /?
setlocal /?
Read also single line with multiple commands using Windows batch file for an explanation of conditional command operator || used on third command line.
The first batch file solution with processing also files in subfolders:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
pushd "%~dp0Folder1" || exit /B
for /F "delims=" %%I in ('dir "(*)*.txt" /A-D-L /B /S 2^>nul') do (
set "FullName=%%I"
set "FileName=%%~nI"
setlocal EnableDelayedExpansion
set "NewName=!FileName:(1)=(-125)!"
set "NewName=!NewName:(2)=(-124)!"
set "NewName=!NewName:(3)=(-121)!"
set "NewName=!NewName:(4)=(-117)!"
set "NewName=!NewName:(5)=(-120)!"
set "NewName=!NewName:(6)=(-116)!"
set "NewName=!NewName:(7)=(-115)!"
set "NewName=!NewName:(8)=(-127)!"
set "NewName=!NewName:(9)=(-126)!"
set "NewName=!NewName:(10)=(-100)!"
ren "!FullName!" "!NewName!%%~xI"
endlocal
)
popd
endlocal
The second batch file solution with processing also files in subfolders:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
pushd "%~dp0Folder1" || exit /B
for %%# in ("1 125" "2 124" "3 121" "4 117" "5 120" "6 116" "7 115" "8 127" "9 126" "10 100") do for /F "tokens=1,2" %%G in (%%#) do for /R %%I in ("(%%G)*.txt") do for /F "tokens=1* delims=)" %%J in ("%%~nxI") do ren "%%I" "(-%%H)%%K"
popd
endlocal
The text files with hidden attribute set are ignored by the FOR loop searching recursively in the subdirectory Folder1 of the batch file directory for the files with the number in round brackets assigned to the loop variable G.

Can I use FOR /L counter variable in the FOR command?

::for /l %%n in (0, 1, 6) do (
for /F "skip=1 delims=" %%i in (path.txt) do set "dirvar=%%i"&goto nextline
:nextline
for /F "skip=1 delims=" %%i in (file.txt) do set "filevar=%%i"&goto nextline
:nextline
for /F "skip=1 delims=" %%i in (dotonefile.txt) do set "dotvar=%%i"&goto nextline
:nextline
SET dirvar=%dirvar%
SET filevar=%filevar%
SET dotvar=%dotvar%
SET dirfile=%dirvar%%filevar%
SET dirdotfile=%dirvar%%dotvar%
IF EXIST %dirfile% (
del %dirdotfile%
) ELSE (
rename %dirdotfile% %dirfile%
)
::)
My batch script above works fine in that it runs one time. It reads the 2nd line from three separate text files into variables. Then it tests to see if a filename is in a directory and if it is named IMG001.jpg it deletes IMG001.1.jpg. in the same directory. If IMG001.jpg is NOT found in the directory, it renames IMG001.1.jpg in the directory to IMG001.jpg.
path.txt is just a text file with a list of folder paths like:
F:\My Pictures\2005-Misc\
F:\My Pictures\2006-Misc\
F:\My Pictures\2007-Misc\
file.txt is just a text file with a list file names, where line 1 is a file in the directory that's also line 1 of the path.txt file. So there could be a IMG001.jpg in the 2005-Misc folder, could be a IMG001.jpg in the 2006-Misc folder, and there could be a IMG001.jpg in the 2007-Misc folder:
IMG001.JPG
IMG001.JPG
IMG001.JPG
Similarly with dotonefile.txt, it's a list of filenames that ARE in the corresponding directory listed in path.txt. So there IS a IMG001.1.jpg in folder 2005-Misc, there's one in 2006-Misc, and there's one in 2007-Misc.
IMG001.1.JPG
IMG001.1.JPG
IMG001.1.JPG
I want to loop this script and repeat it so it reads in lines 1 through n (n can be hard coded, above it is currently 7) from the text files to variables, then tests and renames for each filename.
I tried uncommenting the first and last lines and then in the three for loops, I replaced the hardcoded "1" with "%%n" but the batch file won't run erroring with "the sntax of the command is incorrect". Below is my attempt that doesn't work. Any advice on how to tweak it to run? I've tried all kinds of combinations of making a new count variable that increments by 1 at the end, using delayed expansion in various forms of variables, nothing works.
for /l %%n in (0, 1, 6) do (
for /F "skip=%%n delims=" %%i in (path.txt) do set "dirvar=%%i"&goto nextline
:nextline
for /F "skip=%%n delims=" %%i in (file.txt) do set "filevar=%%i"&goto nextline
:nextline
for /F "skip=%%n delims=" %%i in (dotonefile.txt) do set "dotvar=%%i"&goto nextline
:nextline
SET dirvar=%dirvar%
SET filevar=%filevar%
SET dotvar=%dotvar%
SET dirfile=%dirvar%%filevar%
SET dirdotfile=%dirvar%%dotvar%
IF EXIST %dirfile% (
del %dirdotfile%
) ELSE (
rename %dirdotfile% %dirfile%
)
)
The main problem is that Windows command processor cmd.exe does not support labels inside command blocks which are parsed completely before executing the command making use of the command block. Please read for details How does the Windows Command Interpreter (CMD.EXE) parse scripts?
The solutions is using a subroutine.
#echo off
setlocal EnableExtensions DisableDelayedExpansion
for /L %%N in (0,1,6) do call :ProcessFiles %%N
endlocal
goto :EOF
:ProcessFiles
if not %1 == 0 ( set "SkipOption=skip=%1 " ) else ( set "SkipOption=" )
set "DirVar="
for /F "%SkipOption%eol=| delims=" %%I in (path.txt) do set "DirVar=%%I" & goto GetFileVar
:GetFileVar
set "FileVar="
for /F "%SkipOption%eol=| delims=" %%I in (file.txt) do set "FileVar=%%I" & goto GetDotVar
:GetDotVar
set "DotVar="
for /F "%SkipOption%eol=| delims=" %%I in (dotonefile.txt) do set "DotVar=%%I" & goto CheckFile
:CheckFile
set "DirFile=%DirVar%%FileVar%"
set "DirDotFile=%DirVar%%DotVar%"
if exist "%DirFile%" (
del "%DirDotFile%"
) else (
rename "%DirDotFile%" "%DirFile%"
)
goto :EOF
A smarter approach would be using this batch file code without usage of text files at all.
#echo off
setlocal EnableExtensions DisableDelayedExpansion
for /F "eol=| delims=" %%I in ('dir "F:\My Pictures\*.1.JPG" /A-D /B /S 2^>nul') do (
for %%J in ("%%~dpnI") do (
if exist "%%~dpnJ%%~xI" (
del "%%I"
) else (
ren "%%I" "%%~nJ%%~xI"
)
)
)
endlocal
The FOR loop starts with %ComSpec% /C one more cmd.exe command process in background to execute the command line:
dir "F:\My Pictures\*.1.JPG" /A-D /B /S 2>nul
DIR searches with the specified options for
files because of option /A-D (attribute not directory)
matching case-insensitive the pattern *.1.JPG
in directory F:\My Pictures and all its subdirectories because of option /S
and outputs in bare format because of option /B just
file name with file extension and with full path because of option /S.
DIR would output an error message in case of no file can be found in entire directory tree matching these criteria. This error message is suppressed by redirecting it to device NUL.
Read the Microsoft article about Using Command Redirection Operators for an explanation of 2>nul. The redirection operator > must be escaped with caret character ^ on FOR command line to be interpreted as literal character when Windows command interpreter processes this command line before executing command FOR which executes the embedded dir command line with using a separate command process started in background.
FOR captures everything output to handle STDOUT of started command process and processes the captured text line by line after started cmd.exe finished.
FOR ignores empty lines which do not occur here at all. FOR would also ignore lines starting with ; because of being the default for end of line option. As DIR outputs the file names with full path, it is not possible that a line starts with ;. But eol=| is nevertheless used to define the vertical bar as end of line which no folder/file name can contain ever.
FOR splits up by default each line into substrings (tokens) using normal space and horizontal tab character as delimiters. This behavior is not wanted here as file path could contain a space character. For that reason delims= is used to define an empty list of delimiters which disables the line splitting behavior.
The inner FOR is used to get assigned to loop variable J just the string left to .1.JPG.
The IF condition checks if there is already a file *.JPG for current file *.1.JPG in same directory as current file in which case the file *.1.JPG is deleted or otherwise the renamed to *.JPG if this file deletion or file rename operation is permitted at all depending on read-only attribute, file permissions of current account and current file sharing access permissions.
But let us assume the image file names can be any file name matching *.jpg and there can be not only *.1.jpg, but also *.2.jpg to *.99.jpg image files, i.e. any number after a dot before file extension .jpg. In this case DIR is not enough to get the list of file names with file extension and full path. It is additionally necessary to use FINDSTR with a regular expression to filter the list of file names.
#echo off
setlocal EnableExtensions DisableDelayedExpansion
for /F "eol=| delims=" %%I in ('dir "F:\My Pictures\*.*.jpg" /A-D /B /S 2^>nul ^| %SystemRoot%\System32\findstr.exe /I /R "\.[0123456789][0123456789]*\.jpg$"') do (
for %%J in ("%%~dpnI") do (
if exist "%%~dpnJ%%~xI" (
del "%%I"
) else (
ren "%%I" "%%~nJ%%~xI"
)
)
)
endlocal
First FINDSTR outputs just lines read from STDIN which
matches case-sensitive because of option /I
the regular expression \.[0123456789][0123456789]*\.jpg$
as explicitly declared with option /R.
The regular expression matches a string consisting of a dot, one or more digits, one more dot and the string jpg found at end of line. So a file name like Hello.World.jpg output by DIR is not matched by FINDSTR and therefore not output by FINDSTR and so not processed by FOR.
But a file name like Hello.World.393.jpg is processed and either deleted or renamed to Hello.World.jpg depending on existence of Hello.World.jpg in same directory.
For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.
call /?
del /?
dir /?
echo /?
endlocal /?
findstr /?
for /?
goto /?
if /?
ren /? or rename /?
set /?
setlocal /?
See also Where does GOTO :EOF return to?

batch rename file while keeping part rar number

Like the title suggests I want to batch rename files but keep the part of rar file.
Example:
File-01.part1.rar
File-01.part2.rar
Output:
Newfile__01.part1.rar
Newfile__01.part2.rar
Below is the rename part of the code.
SETLOCAL EnableDelayedExpansion
REM Set your Year, Month, Day variable values here.
REM They will be used for file renaming.
CD "D:\test\rename"
FOR /F "usebackq tokens=* delims=" %%A IN (`DIR "*.rar" /B /A:-D`) DO (
REM Extract the last 2 chars of the file name.
SET FileName=%%~nA
SET First4=!FileName:~0,5!
SET Last2=!FileName:~-2!
REM Rename the file, inserting the new data.
RENAME "%%A" "!First4!__!Last2!%%~xA"
)
ENDLOCAL
Here's an example script based on my assumption of what you wanted to do:
#Echo Off
SetLocal EnableDelayedExpansion
Set "sd=D:\test\rename"
Set "xf=.rar"
If Not Exist "%sd%\*%xf%" Exit /B
CD /D "%sd%" 2>Nul || Exit /B
Set "ds="
For /F "Tokens=1-3 Delims=/ " %%A In ('RoboCopy/NJH /L "\|" Null'
) Do If Not Defined ds Set "ds=%%A%%B%%C"
For %%A In ("*%xf%") Do (Set "fn=%%~nA"
For %%B In ("!fn!") Do (Set "fx=%%~xB"
If /I Not "!fx:.part=!"=="%%~xB" Set "fn=%%~nB")
Ren "%%A" "!fn:~,4!_%ds%_!fn:~-2!!fx!%xf%$")
Ren "*%xf%$" "*%xf%"
I have slotted the year, month, day variable, %ds% in between the two underscores, meaning:
File-01.part1.rar would be renamed to File_20180523_01.part1.rar
Testing18.part2.rar would be renamed to Test_20180523_18.part2.rar
Archive02.rar would be renamed to Arch_20180523_02.rar.
Try this batch file after modification of folder path in third line:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
set "Folder=D:\test\rename"
for /F "eol=| delims=" %%A in ('dir "%Folder%\File-01.part*.rar" /A-D-H /B /ON 2^>nul') do (
for /F "eol=| delims=" %%B in ("%%~nA") do ECHO ren "%Folder%\%%A" "Newfile__01%%~xB%%~xA"
)
endlocal
pause
Note: The command ECHO is used here on line 6 to just demonstrate what would be the rename command line. Run the batch file as is for verification. When everything looks okay, remove ECHO and run the batch file once again to really rename the files.
This batch file runs FOR which runs the command DIR with using a separate command process started in background with cmd.exe /C to output
just the names in bare format because of /B
of only non hidden files because of /A-D-H (attribute not directory and not hidden)
sorted by name because of /ON
matching in specified folder the wildcard pattern File-01.part*.rar.
Read also the Microsoft article about Using Command Redirection Operators for an explanation of 2>nul. The redirection operator > must be escaped with caret character ^ on FOR command line to be interpreted as literal character when Windows command interpreter processes this command line before executing command FOR which executes the embedded dir command line with using a separate command process started in background. 2>nul redirects the error message output on no file matching the criteria from handle STDERR to device NUL to suppress it.
FOR captures the output of started command process and processes it line by line with ignoring empty lines.
The default end of line character ; is modified with eol=| from semicolon to vertical bar. FOR ignores by default lines starting with a semicolon. A file name can start with a semicolon. But a file name can't contain a vertical bar.
FOR splits up by default a line on spaces/tabs and assigns just first part to specified loop variable A. The line splitting behavior is disabled by delims= which specifies an empty list of delimiters resulting in getting the file name with file extension but without file path as output by DIR assigned to the loop variable.
The inner FOR loop processes as string just the file name without file extension. This is the string from first character up to character before last dot, i.e. File-01.part1 and File-01.part2 and assigns this part to loop variable B. For the inner FOR the file extension is again everything after last dot which is .part*. The real file extension .rar of the file is unknown for the inner FOR loop processing just a file name string.
The command REN renames the current file referenced full path to new file name with keeping .part* referenced with %%~B from inner FOR loop and original file extension .rar from outer FOR loop.
For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.
dir /?
echo /?
endlocal /?
for /?
pause /?
ren /?
setlocal /?

Rename multiple files in a directory using batch script

I have about 1000 images and they have name like "IMG-12223". I want to rename them to 1 2 3 4 ... 1000. How can I do that. I have written a batch script which list the files but I don't know how to rename each file. e.g. rename first image with name "IMG-12223" to 1 , second image with name "IMG-23441" to 2 and so on ...
for /r %%i in (*) do (
echo %c%
)
Here's the script. Just put the script in your folder and run it.
#echo off & setlocal EnableDelayedExpansion
set a=1
for /f "delims=" %%i in ('dir /b *') do (
if not "%%~nxi"=="%~nx0" (
ren "%%i" "!a!"
set /a a+=1
)
)
If you want to keep the extensions, i.e. rename "IMG-12223.jpg", "IMG-12224.jpg", etc to "1.jpg", "2.jpg", etc, you may use the following script.
#echo off & setlocal EnableDelayedExpansion
set a=1
for /f "delims=" %%i in ('dir /b *.jpg') do (
ren "%%i" "!a!.jpg"
set /a a+=1
)
[Update] Here're explanations for the lines mentioned in Jack's comment.
setlocal EnableDelayedExpansion
In general, we want the variable a to be delayed expansion when it's executed but not the line is read. Without it, the variable a cannot get its increased value but always 1.
For the detail of EnableDelayedExpansion, please refer to the answer https://stackoverflow.com/a/18464353/2749114.
for /f "delims=" %%i in ('dir /b *.jpg')
Here dir with /b option, lists only file names of all jpg files.
The for loop traverses and renames all jpg files.
For the delims option, since the default delimiter character is a space, without the option delims=, it fails with the image files with spaces in the file names. I.E. for an image file named "img with spaces.jpg", without the option, the value of %%i is "img" but not the whole name "img with spaces.jpg", which is incorrect.
For for loop, please refer to the page http://ss64.com/nt/for_f.html.
if not "%%~ni"=="%~n0"
I have change it to if not "%%~nxi"=="%~nx0" to be more accurate. And the codes attached have been updated.
It's actually used to avoid to rename the bat file itself. If we limit the renaming only upon "jpg" files, then the line is not needed.
%%~nxi is the file name with extension for each file traversed. And %~nx0 is the running bat file with extension. For details, please refer to the page DOS BAT file equivalent to Unix basename command?.
There is no need for a batch script. A simple one liner from the command line can do the job :-)
I use DIR /B to generate the list of files, piped to FINDSTR to number the files, all enclosed withn FOR /F to parse the result and perform the rename.
for /f "delims=: tokens=1*" %A in ('dir /b *.jpg^|findstr /n "^"') do #ren "%B" "%A%~xB"
Double the percents if you want to put the command in a batch script.
Try this, you have pair of namevalues in a text file then loop values and do the magic. Namevalues are separated by empty spaces. This allows you to map old->new filenames accordingly. Or you keep idx+1 counter and use it for new filenames.
keyvalue.bat
#echo off
set idx=0
for /F "tokens=1,2" %%A in (keyvalue.txt) do call :PROCESS "%%A" "%%B"
GOTO :END
:PROCESS
set var1=%~1
set var2=%~2
set /A idx=%idx%+1
echo %var1% goes to %var2% (%idx%)
GOTO :EOF
:END
pause
keyvalue.txt
file888.dat newfile1.dat
file333.dat newfile2.dat
file9.dat newfile3.dat
file01.dat newfile4.dat

use * with a batch file to get filenames

I am using Windows XP and need to create a batch file to move tok.filename to filename.tok.
This works for one file if I type in fix.bat tok.filename.
set filename=%1
set newname=%filename:~4,45%
ren %1 %newname%.tok
I need to type in fix.bat tok*, but this puts tok* in the filename.
How do I get it to read all the files into the filename one at a time?
Use a for statement.
setlocal enabledelayedexpansion
for %%i in (tok.*) do (
set filename=%%i
set newname=!filename:~4,45!
ren %%i !newname!.tok
)
Enabling the delayed expansion makes it so that the variables are evaluated at the time they are used.
Alternatively, since you already have a batch file that works, you could write another batch file that uses the for statement, which calls your working batch file -- like this:
for %%i in (tok.*) do call fix.bat %%i
Or you could run it directly from the command line like this:
for %i in (tok.*) do call fix.bat %i
No need for a batch script
for %F in (tok.*) do for /f "delims=." %X in ("%~xF") do ren "%F" "%X.%~nF"
Double up the percents if used within a batch script.
The above may not give the desired result if more than one . appears in a file name.
For example tok.part1.part2 would become part2.tok.part1.
If you want part1.part2.tok instead, then you can use the following simple script.
#echo off
ren tok.* .*?.tok
for %%F in (.*.tok) do for /f "tokens=* delims=." %%A in ("%%F") do ren "%%F" "%%A"
For an explanation of how that 1st REN works in the 2nd script, see How does the Windows RENAME command interpret wildcards?
I suppose an esoteric argument could be made that a name like tok..name would become name.tok when it should be .name.tok. That could be fixed by using:
#echo off
setlocal disableDelayedExpansion
ren tok.* .*?.tok
for %%F in (.*.tok) do (
set "name=%%F"
setlocal enableDelayedExpansion
ren "!name!" "!name:~1!"
endlocal
)
The nice thing about the solutions above is they don't rely on the length of "tok". A string value of any length could be substituted for "tok" and the code works just as well.
The James L solution works well for a constant length. That solution can be improved a bit.
The 2nd argument to the substring operation is not needed. Removing it lets the solution work no matter how long the full original name is.
The code will fail if a name has an ! in it. Fixed by toggling delayed expansion on and off.
The filenames should be quoted in the REN statement in case of spaces or special characters
.
#echo off
setlocal disableDelayedExpansion
for %%i in (tok.*) do (
set "filename=%%i"
setlocal enableDelayedExpansion
ren "!filename!" "!filename:~4!.tok"
endlocal
)
you can also do the same without delayed expansion (which is slow).
Also, if there is only one dot, without explicitly using lengths of name parts.
%~n expands to filename without extension, and %~x to dot with extension (so I remove dot with :~1).
Also, using %* in for, you may pass arbitrary number of arguments.
And even more. If you add /R bewteen for and %%I (you'll get for /R %%I), it will recurse into subdirs also.
Whole batch file:
for %%I IN (%*) do call :Rename "%~I"
exit /b
:Rename
set newname=%~x1
ren %1 "%~dp1%newname:~1%.%~n1"
exit /b

Resources