I have a bunch of jpg files named IMG_0001, IMG_0002, etc. The problem was that there I had to delete a couple of them, so I need to rename the files to fill in the gaps. In essence,
IMG_0001, IMG_0002, IMG_0004, IMG_0006
are renamed
IMG_0001, IMG_0002, IMG_0003, IMG_0004.
Thus filling in the gaps caused by the files I deleted. However, the bat file I wrote to do this sometimes jumbles the files out of order, so what was originally IMG_0001 would become IMG_0002, and IMG_0003 would become IMG_0001. How can I ensure that my bat file loops through the files in order of name?
This is my bat file:
#echo off
set i=1
set y=0000
for %%f in (*.jpg) do call :renameit "%%f"
goto done
:renameit
set x=%y%%i%
ren %1 IMG_%x:~-4%.jpg
set /A i+=1
:done
I don't think FOR supports ordering on its own, but DIR does with the /on ("order by name") switch. So, try replacing your FOR loop with this:
for /f "tokens=*" %%f in ('dir /b /on *.jpg') do call :renameit "%%f"
#echo off
setlocal enableextensions enabledelayedexpansion
for /f "tokens=1,* delims=:" %%a in ('dir /a-d /on /b "IMG_*.jpg"^|findstr /n "^"') do (
set /a "n=%%a+10000"
ren "%%b" "IMG_!n:~-4!.jpg"
)
This just uses findstr to numerate the list of retrieved files (each lines is in the format number:filename) and uses this numeration to do the rename of files.
Related
I have went through a lot of guides for it, but havent found a way to do something similar to lets say turn all files in folder, like these files:
djhwu4s_cat_ruhg29.png
397y_dog_j0929_ej93.png
8yhh_owl.png
into these:
_cat.png
_dog.png
_owl.png
So basically removing everything from file names but a list of predefined strings i am searching for. In example above i would define list as "_cat", "_dog", "_owl". I know that each file will have only one of these variables, and there will be only one file with each of them in folder.
Will appreciate any tips on how to achieve that. Thanks in advance!
edit:
Here is what i came up with (with stuff i can understund) and what seems to be working fine now.
#echo off
setlocal enabledelayedexpansion
set v1=_cat-cat
set v2=_cat-owl
set v3=_cat
set v4=_dog
set v5=_owl
set v6=_horse
FOR /L %%a IN (1,1,6) DO (
rem echo %%a
rem echo !v%%a!
FOR /f %%f in ('dir /b /a:-D *!v%%a!.*') DO (
REN %%f !v%%a!.*
)
FOR /f %%f in ('dir /b /a:-D *!v%%a!_*.*') DO (
REN %%f !v%%a!.*
)
)
rem using two passes of this simpler code i can grasp and understund with dot and with underscore
rem after constructed variables value i make sure cat-cat is not recognised as and renamed to cat
rem no matter if im getting file with that variable as the last string before extension or another underscore
rem Gonna test it in combat now
For some reason this stuff doesnt work with files containing spaces and characters like:
"ab’c efg_dog.png"
FOR /L %%a IN (1,1,36) DO (
FOR /f %%f in ('dir /b /l /a:-D *!v%%a!.*') DO (
REN "%%f" "!v%%a!.*"
)
FOR /f %%f in ('dir /b /l /a:-D *!v%%a!_*.*') DO (
REN "%%f" "!v%%a!.*"
)
)
After further testing i have realised the problem starts with the %%f, and not the REN function as i thought. echo %%f before ren gives just the first part of the name to the first space, hence the REN function cant find the file. In case of "ab’c efg_dog.png" after finding the file with dir, the %%f becomes just "ab’c".
edit: After more tests and experiments and adding those "delims" to the code, the echo now shows proper, full names to be renamed, but it replaces that weird ’ character with ' for the REN command and thats why it still cant find the file to rename.
FOR /L %%a IN (1,1,36) DO (
FOR /f "delims=" %%f in ('dir /b /l /a:-D *!v%%a!.*') DO (
echo %%f
echo REN "%%f" "!v%%a!.*"
)
FOR /f "delims=" %%f in ('dir /b /l /a:-D *!v%%a!_*.*') DO (
echo %%f
echo REN "%%f" "!v%%a!.*"
)
)
#ECHO OFF
SETLOCAL
rem The following setting for the directory is a name
rem that I use for testing and deliberately includes spaces to make sure
rem that the process works using such names. These will need to be changed to suit your situation.
SET "sourcedir=u:\your files"
PUSHD "%sourcedir%"
FOR /f "delims=" %%e IN ('dir /b /a-d "*_*" 2^nul ^|findstr /v /b "_"') DO (
FOR /f "tokens=2delims=_." %%y IN ("%%e") DO ECHO REN "%%e" "_%%y%%~xe"
)
POPD
GOTO :EOF
For lack of examples, here's a start.
Always verify against a test directory before applying to real data.
Process the list of filenames that match *_*; find those names that do not start _, pick the second string between the delimiters _ and . and rename using that string (in %%y), prefixed by _ and appended with the original extension.
The ren command is simply echoed to the screen for verification. When happy, remove the echo before the ren to actually execute the rename.
I have several pictures of my students in a folder, and a list with their names in a text file.
I would like to creat a batch file to rename the pictures using the text file (names.txt) so that every picture has the name of the student.
All the pictures are in .png format. I searched this site and tried the following code :
#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
rem Load the list of new filenames
set i=0
for /F "delims=" %%a in (names.txt) do (
set /A i+=1
set "newname[!i!]=%%a"
)
rem Do the rename:
set i=0
for /F "delims=" %%a in ('dir /b /o:n *.png') do (
set /A i+=1
for %%i in (!i!) do ren "%%a" "!newname[%%i]!"
)
I creat the batch file in the folder and when I execute it, there is nothing happening.
I think it is not picking the right folder to work into, but I'm not sure.
Example of files:
1.png
2.png
3.png
Example of names.txt
1_john_dalton
2_carol_denvers
3_steve_austin
Based on your comments and the construction of the current code, it seems you want something like this:
#echo off
for /F "delims=" %%a in (names.txt) do (
for /f %%i in ('dir /b /o:n *.png') do echo ren "%%i" "%%a%%~xi"
)
This above will simply echo the result and not do the rename, only if you are happy with the results, can you remove echo from the last line, before ren.
Your example seems to want to resuse the old numeric name as well, so if indeed the case, then this should be it:
#echo off
for /F "delims=" %%a in (names.txt) do (
for /f %%i in ('dir /b /o:n *.png') do echo ren "%%i" "%%a[%%~ni]%%~xi"
)
My code is able to rename the .txt file, but not able to target the pdf to rename at the same time with the same information extracted from the .txt file.
I've tried to put
for /f "delims=" %%i in ('dir /a-d/b *.pdf') do (
rename "!fname!" "!nname!.pdf"
in different spots where I would think they might work, but if it's inside the other /f "delims="block for the .txt files, it does not run and if it's outside, it won't grab the same name.
setlocal
cd File Location
::Next Targets .txt files, makes variables, modifies the variable, and renames the .txt
for /f "delims=" %%i in ('dir /a-d/b *.txt') do (
set "nname="
set "fname=%%~i"
for /f "usebackq skip=4 delims=" %%f in ("%%~i") do if not defined nname set "nname=%%f"
setlocal enabledelayedexpansion
set "nname=!nname:~12,10!"
rename "!fname!" "!nname!.txt"
)
::I tried to pull the same variables while targeting the .pdf files, but it wouldn't get the variables.
for /f "delims=" %%i in ('dir /a-d/b *.pdf') do (
rename "!fname!" "!nname!.pdf"
)
endlocal
pause
I expected the second block to be able to pule the same variables(file names) from the first block, but it just does nothing.
Well, I figured out how to rename the pdf's, as the txt's weren't necessary to rename, but instead to pull information from to rename the pdf's
setlocal
cd Directory
for /f "delims=" %%i in ('dir /a-d/b *.txt') do (
set "nname="
set "fname=%%~i"
for /f "usebackq skip=5 delims=" %%f in ("%%~i") do if not defined nname set "nname=%%f"
setlocal enabledelayedexpansion
set "nname=!nname:~12,10!"
set "fname=!fname:~0,-4!"
rename "!fname!.pdf" "!nname!.pdf"
)
endlocal
pause
This removes the ending to the variable and searches that +.pdf to rename
I have built 2 batch files, which each have his own function first one:
Changes the file name to today's date
SET src_folder="C:\DIR_A\"
SET tar_folder="C:\DIR_A\DIR_B"
for /f %%a IN ('dir "%src_folder%" /b') do REN *.xml %time:~0,2%%time:~3,2%%time:~6,2%_%date:~-10,2%%date:~-7,2%%date:~-4,4%.xml
pause
Second one:
Move files from DIR_A to DIR_B
SET src_folder="C:\DIR_A\"
SET tar_folder="C:\DIR_A\DIR_B"
for /f %%a IN ('dir "%src_folder%*.xml" /b') do move %src_folder%\%%a %tar_folder%
pause
My question is: how can I combine them both in one loop?
Second question is with the naming loop. The loop only names the first XML file, and says that the name already exist. That's true therefor is there anyway to make it pause before it name again, so the files have different names?
Simple: to use several commands, use a code block:
for %%a IN ("%src_folder%") do (
echo RENAME %%a
echo COPY %%a
)
Note: keep in mind, you may need to use delayed expansion (not in this example though)
Applied to your code:
#echo off
setlocal enabledelayedexpansion
SET src_folder="C:\DIR_A\"
SET tar_folder="C:\DIR_A\DIR_B"
for %%a IN ("%src_folder%*.xml") do (
REN "%%a" !time:~0,2!!time:~3,2!!time:~6,2!_%date:~-10,2%%date:~-7,2%%date:~-4,4%.xml
move "%src_folder%\%%a" "%tar_folder%"
timeout 1 >nul
)
Note: here you need delayed expansion (at least) with the time variable. Consider to delay date too (would be "best practice")
Alternatively: first rename all files, then copy them in one go:
#echo off
setlocal enabledelayedexpansion
SET src_folder="C:\DIR_A\"
SET tar_folder="C:\DIR_A\DIR_B"
for %%a IN ("%src_folder%*.xml") do (
REN "%%a" !time:~0,2!!time:~3,2!!time:~6,2!_%date:~-10,2%%date:~-7,2%%date:~-4,4%.xml
timeout 1 >nul
)
move "%src_folder%\*.xml" "%tar_folder%\"
Simplest is to do it in one go, without rename, just move them with a new name:
#echo off
for %%a IN (*.xml) do (
move "%source_folder%\%%a" "%tar_folder%\%time:~0,2%%time:~3,2%%time:~6,2%_%date:~-10,2%%date:~-7,2%%date:~-4,4%.xml"
)
pause
Other methods:
#echo off
setlocal enabledelayedexpansion
for /f %%a IN ('dir /b /a-d "%src_folder%\*.xml"') do (
set "myren=%time:~0,2%%time:~3,2%%time:~6,2%_%date:~-10,2%%date:~-7,2%%date:~-4,4%.xml"
ren "%%a" "!myren!"
move "%src_folder%\!myren!" "%tar_folder%"
)
pause
Or without delayedexpansion:
#echo off
for /f %%a IN ('dir /b /a-d "%src_folder%\*.xml"') do (
move "%%a" "%tar_folder%"
ren "%tar_folder%\%%a" "%time:~0,2%%time:~3,2%%time:~6,2%_%date:~-10,2%%date:~-7,2%%date:~-4,4%.xml"
)
pause
or even:
#echo off
for /f %%a IN ('dir /b /a-d "%src_folder%\*.xml"') do (
ren "%source_folder%\%%a" "%time:~0,2%%time:~3,2%%time:~6,2%_%date:~-10,2%%date:~-7,2%%date:~-4,4%.xml"
)
move /Y "%src_folder%\*.xml" "%tar_folder%"
pause
Simplest, do it in one go:
I have a bunch of files say,
xxx111.txt
xxx112.txt
xxx113.txt
I want to remove the last 3 characters of all the file names and I'm using this script
#echo off
setlocal enabledelayedexpansion
set X=3
for %%f in (*) do if %%f neq %~nx0 (
set "filename=%%~nf"
set "filename=!filename:~,-%X%!"
ren "%%f" "!filename!%%~xf"
)
popd
pause
This runs perfectly when the output filenames are different. However, in the above case all file will be output as xxx.txt and the script throws me the error
"A duplicate file name exists, or the file cannot be found".
Is there any way to tweak this so that duplicate files will be renamed and maybe numbered 1,2,3...?
Unfortunately I cannot install any other software.
#echo off
setlocal EnableDelayedExpansion
set X=3
for /F "delims=" %%f in ('dir /A:-D /B') do if "%%f" neq "%~NX0" (
set "filename=%%~Nf"
set "filename=!filename:~,-%X%!"
if exist "!filename!%%~Xf" call :getNewName "%%~Xf"
ren "%%f" "!filename!%%~Xf"
)
popd
pause
goto :EOF
:getNewName ext
set i=0
:nextNum
set /A i+=1
if exist "%filename%%i%%~1" goto nextNum
set "filename=%filename%%i%"
exit /B
You should not use plain for %%f command when renaming files. Depending on where the new names are placed in the list of original names, they may be processed a second time by the for %%f. Always use for /F for renaming.