Reputation: 5
I run the google drive account for my children's Scouts BSA troop and as such get hundreds and hundreds of pictures from all of the other parents each event. I created a simple little batch that allows me to put all the pics I get in a directory and rename them "Some_Event-1.png, Some_Event-2.png" etc. and for the most part this works great. But some of the presented filenames have spaces in them and that seems to be causing "file not found" problems when running the batch. How can get the rename command in my FOR loop to function whether or not the filename has a space? Code I'm using below:
(note: I pass flags to the batch rather than use user input in the batch. Format is "BATREN.BAT N EXT New_name" where N/%1 is the number want it to start the numbering at, EXT/%2 is the extension i want to target, eg jpg or png, and New_name/%3 is the new name to assign.)
@ECHO OFF
setlocal enabledelayedexpansion
DIR *.%2 /B>C:\Users\MyUser\AppData\Local\Temp\FileList.txt
Set /A CNT=%1
FOR /F %%i IN (C:\Users\MyUser\AppData\Local\Temp\FileList.txt) DO (
REN %%i %3-!CNT!.%2
SET /A CNT+=1
)
EXIT /B
I have tried to find an answer similar to what I'm asking here but there doesn't seem to be one, either I'm blind or an idiot if there already is, so I apologize for that.
Upvotes: 0
Views: 1821
Reputation: 2562
Your troubles comes from quoting and delimiters.
delims
for the FOR
command.REN
command in case you have to provide "spaced" filename targets.EDIT: Thanks to @compo, removing usebackq
as it is for the command and not the output... I'm old...
@ECHO OFF
setlocal enabledelayedexpansion
DIR *.%2 /B>C:\Users\MyUser\AppData\Local\Temp\FileList.txt
Set /A CNT=%1
FOR /F "delims=" %%i IN (C:\Users\MyUser\AppData\Local\Temp\FileList.txt) DO (
REN "%%i" "%3-!CNT!.%2"
SET /A CNT+=1
)
EXIT /B
Explanation: The delims=
option tells to the FOR
command to take every characters until a newline is met. By default, the delimiter of the FOR
command is a blank space, which is why you get only partial filename when they have a blank.
Upvotes: 0
Reputation: 38579
Here's a quick example of how I'd approach the task, without the need to create an intermediate text file:
@Echo Off
SetLocal EnableExtensions DisableDelayedExpansion
Set "Count=%~1"
For /F Delims^=^ EOL^= %%G In ('Dir "*.%~2" /B /A:-D 2^>NUL') Do (
SetLocal EnableDelayedExpansion
Ren "%%G" "%~3-!Count!%%~xG"
EndLocal
Set /A Count += 1
)
The example does not validate that any arguments were received, or whether those received are correct. i.e. That the first one is an integer, the second is a string which does not contain a period, and that the third is a string which does not include any characters which are invalid in a Windows file name. I would advise that any robust solution should perform that validation, which is outside of the scope of your question. Additionally there is no check as to whether any of the intended filenames already exist, and whilst it may not be very likely, a robust solution should probably include code for determining what happens in such scenarios.
The example does however, as per my comment, ensure that there are no delimiters, (delims
), and double-quotes the filename strings, to protect spaces and other problematic characters. Additionally it defines no eof
, (leading end of line), character, because the default is ;
and that is a valid character for a filename to begin with.
You should also be made aware that on systems which have had 8.3 naming enabled, (default), the file glob example: *.jpe
does not list files with the case insensitive extension .jpe
, it lists all items whose names end with a period followed by the string jpe
followed by zero or more non period characters, which would also include .jpeg
. The same is true for *.tif
which would also return .tiff
files. Now this may not be a problem, and could actually be a benefit, but if it is a possible unwanted issue, you should probably include a filter to ensure that only extensions matching your input are processed, (once again this is outside of the scope of your question).
If you just want to see what would happen, without actually performing the rename operation, you could change the code to this, which has been modified only so that any output does not omit possible !
characters in the enumerated filenames, (due to delayed expansion):
@Echo Off
SetLocal EnableExtensions DisableDelayedExpansion
Set "Count=%~1"
For /F Delims^=^ EOL^= %%G In ('Dir "*.%~2" /B /A:-D 2^>NUL') Do (
Set "FileName=%%G"
SetLocal EnableDelayedExpansion
Echo Ren "!FileName!" "%~3-!Count!%%~xG"
EndLocal
Set /A Count += 1
)
You could of course use this for the actual rename task too, by simply removing Echo
from line 7
.
Upvotes: 1