batch rename multiple files in windows? - windows

I wonder what's wrong with my coding, because it's not working
I want to rename all the png files inside Chris.
but it failed
for /f in ('C:/Users/Chris/Downloads/images/*.png')
do ren "C:\Users\Chris\Downloads\images\*.png" "%date:~10,4%-%date:~4,2%-%date:~7,2%_%HR%%time:~3,2%-img.png"

No need for /f in argument, no need for quotes but your missing a variable declaration
The variable should be used in the do-part otherwise the for is not realy helpful
the for will enumerate the full path so you need to strip the filename using ~n
the do-part must be directly behind the for-statement or it needs to be inside round brackets
here's the complete code:
for %%i in (C:/Users/Chris/Downloads/images/*.png) do (
ren "%%i" "%date:~10,4%-%date:~4,2%-%date:~7,2%_%HR%%time:~3,2%-%%~niimg.png"
)

If order to use a for loop, you need to specify a variable to use (even if you don't use a variable in the loop at all), otherwise you'll get a syntax error. While variables can only be one letter, this is pretty much the only time in batch that variables are case-sensitive, so you've got 52 letters, plus a few additional characters that I've seen used, like #. Additionally, do must always be on the same line as the ).
A for /F loop can process strings, text files, and other batch commands.
To process strings, use double quotes: for /F %%A in ("hello world") do echo %%A
To process batch commands, use single quotes: for /F %%A in ('dir /b') do echo %%A
To process text files, do not use any quotes at all: for /F %%A in (C:\Users\Chris\image_list.txt) do echo %%A
You may also want to go into the directory that you're processing just to make things easier.
pushd C:\Users\Chris\Downloads\images
for /F %%A in ('dir /b *.png') do (
REM I'm not sure what the %HR% variable is supposed to be, so I'm ignoring it.
ren "%%A" "%date:~10,4%-%date:~4,2%-%date:~7,2%_%HR%%time:~3,2%-img.png"
)

Related

Nested FOR with variables

I'm attempting to write a batch script that will go through a list of computers, read a file from the computer, delim the file name, then echo the computer name and the file name result. The issue I'm having is getting the computer name variable to populate in the nested FOR /R command. Here is my script:
#ECHO OFF
SetLocal EnableDelayedExpansion
SET LIST=Computers.txt
FOR /F %%A IN (%LIST%) DO (
FOR /R \\%%A\c$\folder1\folder2 %%B IN (*.txt) DO (
FOR /F "tokens=2 delims=." %%C IN ("%%B") DO (ECHO %%A %%C
)
)
)
EndLocal
The filename is something like RB-C1SRC20160716CL.P17.txt. So the result I am looking for is
MyPCName P17
But I get a blank result. What I have found is that %%A var is being populated from the text file but the %%A var in the FOR /R is not populating. If I ECHO ON the FOR commands I'm seeing FOR /R \%a\folder1\folder2 instead of FOR /R \MyPCName\folder1\folder2. This breakdown is keeping the rest of the script from working properly.
The root directory of a for /R command cannot be given by another for variable (like %%I) nor a variable using delayed expansion (!VAR!), unfortunately. You need to specify it either iterally, by a normally expanded variable (%VAR%) or by an argument reference (%1, %2,...).
A good work-around is to place the for /R loop in a sub-routine and use call to call it from your main routine. The (variable holding the) root path needs to be passed as an argument to call. In the sub-routine it is referred to by an argument reference (like %1).
Take a look at this answer of the post "Get size of the sub folders only using batch command" to see how this can be accomplished.
Another option is to temporarily change into the root directory before the for /R loop, which then defaults to the current working directory. Use pushd"\\%%A\c$\folder1\folder2" to change to the target directory, then put popd behind the for /R loop to return to the former directory.

Change extension of files in windows batch

I am trying to rename a lot of files. I only want to change the extention from ".pdf.OCR.pdf" to ".pdf"
So far I got the following code
rem for /r myPDFfolder %%i in (*.pdf.OCR.pdf) do ren "%%i" "%%~ni.pdf"
But it does not appear to work with the extension that has multiple dots -- what am I doing wrong?
Extension is the part of file name after the last dot.
Use string replacement to strip the unneeded part:
setlocal enableDelayedExpansion
for /f "eol=* delims=" %%i in ('dir /s /b "r:\*.pdf.OCR.pdf"') do (
set "name=%%~nxi"
ren "%%i" "!name:.pdf.OCR=!"
)
P.S. Parsing of dir is used to make the code more robust in case a different text is stripped which might have changed the sorting order and cause for to process the file twice or more times.
There is no need for a batch file. A moderate length one liner from the command prompt can do the trick.
If you know for a fact that all files that match *.pdf.ocr.pdf have this exact case: .pdf.OCR.pdf, then you can use the following from the command line:
for /r "myPDFfolder" %F in (.) do #ren "%F\*.pdf.ocr.pdf" *O&ren "%F\*.pdf.o" *f
The first rename removes the trailing .pdf, and the second removes the .OCR. The above works because *O in the target mask preserves everything in the original file name through the last occurrence of upper-case O, and *f preserves through the last occurrence of lower-case f. Note that the characters in the source mask are not case sensitive. You can read more about how this works at How does the Windows RENAME command interpret wildcards?
If the case of .pdf.ocr.pdf can vary, then the above will fail miserably. But there is still a one liner that works from the command line:
for /r "myPDFfolder" %F in (*.pdf.ocr.pdf) do #for %G in ("%~nF") do #ren "%F" "%~nG"
%~nF lops off the last .pdf, and %~nG lops off the .OCR, which leaves the desired extension of .pdf.
You should not have to worry about a file being renamed twice because the result after the rename will not match *.pdf.ocr.pdf unless the original file looked like *.pdf.ocr.pdf.ocr.pdf.
If you think you might want to frequently rename files with complex patterns in the future, then you should look into JREN.BAT - a regular expression renaming utility. It is pure script (hybrid JScript/batch) that runs natively on any Windows machine from XP onward. Full documentation is embedded within the script.
Assuming JREPL.BAT is in a folder that is listed within your PATH, then the following simple command will work from the command line, only renaming files that match the case in the search string:
jren "(\.pdf)\.OCR\.pdf$" $1 /s /p "myPDFfolder"
If you want to ignore case when matching, but want to force the extension to be lower case, then:
jren "\.pdf\.ocr\.pdf$" ".pdf" /i /s /p "myPDFfolder"
Alternative solution, without delayed expansion (remove ECHO to actually rename any files):
#echo off
rem iterate over all matching files:
for /F "delims=" %%A in (
'dir /S /B /A:-D "myPDFfolder\*.pdf.OCR.pdf"'
) do (
rem "%%~nA" removes last ".pdf"
for /F %%B in ("%%~nA") do (
rem "%%~nB" removes ".OCR" part
for /F %%C in ("%%~nB") do (
rem "%%~nC" removes remaining ".pdf"
ECHO ren "%%~fA" "%%~nC.pdf"
) & rem next %%C
) & rem next %%B
) & rem next %%A
NOTE: The directory tree is enumerated before for iterates through it because otherwise, some items might be skipped or tried to be renamed twice (see this post concerning that issue).

FOR /F processing of CSV with differing number of variables

I'm trying to write a batch script to move thousands of folders from their current location to a new location. I have a CSV with the original/new location info, as such:
[full path of current location],new_dir_1,new_subdir_2,[new_subdir_3],[etc],
In the past I've had good luck using FOR /F, and that's what I'm trying here.
for /f "tokens=1-4 delims=," %g in (text_file.csv) do xcopy "%%g" "d:\%%h\%%i\%%j" /e /i /y
Fails where there aren't enough tokens for variables and I get two trailing backslashes in my destination path.
for /f "tokens=* ....
Fails as well - my understanding was that "tokens=*" would create a token per comma-separated term but maybe I have that wrong? It appears, rather, to take the entire line as one token.
Is there a way to modify my "do" command to only create the destination path as deep as necessary (i.e., if new_subdir_3 doesn't exist, the path should be "d:\new_dir1\new_subdir_2\" and not "d:\new_dir1\new_subdir_2\")?
Thanks.
The tokens=* or tokens=1,* does not work as you think. It will set an aditional replaceable parameter that will contain the rest of the line after the last required token. That is, all the line in the first case or from the second to the end in the second case. But only one variable/replaceable parameter is defined for the *
There is an easy way to solve your problem . Just use an aditional for loop to handle the problematic path
for /f "tokens=1-4 delims=," %%g in (text_file.csv) do (
for %%a in ("d:\%%~h\%%~i\%%~j\.") do xcopy "%%~g" "%%~fa" /e /i /y
)
The %%~fa will return the full path generated by d:\%%~h\%%~i\%%~j\., but all the double backslashes will be removed in the process.

Batch Drag and drop files and folders

I'm trying to copy multiple files and folders from a drag and drop selection using a solution I think should look something like this:
mkdir newdir
for %%a in ("%*") do (
echo %%a ^ >>new.set
)
for /f "tokens=* delims= " %%b in ('type "new.set"') do (
SET inset=%%b
call :folderchk
if "%diratr%"=="d" robocopy "%%b" "newdir" "*.*" "*.*" /B /E && exit /b
copy /Y %%b newdir
)
exit /b
:folderchk
for /f tokens=* delims= " %%c in ('dir /b %inset%') do (
set atr=%~ac
set diratr=%atr:~0,1%
)
I've tried throwing together code from the following examples but I'm stuck:
http://ss64.com/nt/syntax-dragdrop.html
Drag and drop batch file for multiple files?
Batch Processing of Multiple Files in Multiple Folders
Handling of special characters with Drag&Drop is tricky, as doesn't quote them in a reliable way.
Spaces are not very complicated, as filenames with spaces are automatically quoted.
But there are two special characters, who can produce problems, the exclamation mark and the ampersand.
Names with an ampersand will not automatically quoted, so the batch can be called this way
myBatch.bat Cat&Dog.txt
This produces two problems, first the parameters aren't complete.
In %1 and also in %* is only the text Cat the &Dog.txt part can't be accessed via the normal parameters, but via the cmdcmdline variable.
This should be expanded via delayed expansion, else exclamation marks and carets can be removed from the filenames.
And when the batch ends, it should use the exit command to close the cmd-window, else the &Dog.txt will be executed and produce normally an error.
So reading the filenamelist should look like
#echo off
setlocal ENABLEDELAYEDEXPANSION
rem Take the cmd-line, remove all until the first parameter
set "params=!cmdcmdline:~0,-1!"
set "params=!params:*" =!"
set count=0
rem Split the parameters on spaces but respect the quotes
for %%N IN (!params!) do (
echo %%N
)
pause
REM ** The exit is important, so the cmd.ex doesn't try to execute commands after ampersands
exit
This is also described in the link you refereneced Drag and drop batch file for multiple files?

Batch For Loop Escape Asterisk

I am attempting to create a batch for loop (Windows XP and newer command prompts) that iterates through a string containing one or more asterisks. How can I do this? Here is an example:
#FOR %%A IN (A* B) DO #ECHO %%A
The expected output (what I am trying to get) is the following:
A*
B
However, what I am actually getting with the command above is B and only B. For some reason, everything with an asterisk is being ignored by the loop. I have attempted escaping the asterisk with 1-4 carets (^), backslashes (\), percent signs (%), and other asterisks (*), all to no avail. Thanks in advance for illuminating me.
IN CASE YOU WANT MORE INFORMATION:
The purpose of this is to parse a path out of a list of space-separated partial paths. For example, I want to copy C:\Bar\A.txt, C:\Bar\B.txt, and C:\Bar\C*.txt to C:\Foo\ using the following approach:
#SET FILE_LIST=A B C*
#FOR %%A IN (%FILE_LIST%) DO #COPY C:\Bar\%%A.txt C:\Foo\
If there is another alternative way to do this (preferably without typing each and every copy command since there are ~200 files, which is the same reason I don't want to store the full path for every file), I would appreciate the help. Thanks again,
-Jeff
the asterisks works the way its intended, in your case,
#FOR %%A IN (A* B) DO #ECHO %%A
expands A* to all the files that begin with A.
A possible way to do what you want, is just to use this expansion
#ECHO off
PUSHD C:\bar
SET FILE_LIST=A.txt B.txt C*.txt
FOR %%A IN (%FILE_LIST%) DO (
IF EXIST %%A COPY %%A C:\Foo\
)
POPD
This may help:
#echo off
set "it=a*b .txt-b*.txt-c*.txt-d.txt"
set /a i=0,fn=3
:startLoop
set /a i=i+1
for /f "tokens=%i%delims=-" %%m in ("%it%") do echo %%m
if %i% lss %fn% goto:startLoop

Resources