Reputation: 41
I am trying to write a patch file that will do the following:
I am having some problems hence my post here. I have been able to piece this code together from other posts on this site. This is what I have so far. Go easy on me it has been 18 years since I did any programing in college.
I am using a program called Take Command by JP Software so I could use some sort of debugger and try to figure out what I was doing wrong.
Thank you for any and all help.
@Echo OFF
set /A xcount=0
set root=c:\clients
Set logfilename=Changed.txt
cd %root%
for /f "delims=" %%a in ('dir /a:-d /o:n /b /s *.pdf *.xls') do call :next "%%a"
echo. >> %root%\%logfilename%
echo End of file > %root%\%logfilename%
pause
GOTO:EOF
:next
set "current=%~nx1"
set "newname=%~nx1"
set "newname=%newname:&=and%"
set "newname=%newname:#=%"
set "newname=%newname: LTD.=%"
set "newname=%newname:%=%"
set "newname=%newname::=%"
If "%current%" == "%newname%" goto nope
SET /A xcount+=1
ren "%current%" "%newname%"
echo "%current%" "%newname%"
echo %xcount% - "%current%" "%newname%" > %root%\%logfilename%
:nope
Upvotes: 4
Views: 160
Reputation: 79982
Given a directory u:\sourcedir\t w o
Volume in drive U has no label.
Volume Serial Number is 0460-0000
Directory of u:\sourcedir\t w o
14/12/2014 00:05 <DIR> .
14/12/2014 00:05 <DIR> ..
14/12/2014 00:28 0 dum myfile2.txt
14/12/2014 00:28 0 file1.xls
14/12/2014 00:28 0 file2.xls
14/12/2014 00:28 0 file3.xls
14/12/2014 00:28 0 amper&1.pdf
14/12/2014 00:28 0 amper&2.pdf
14/12/2014 00:28 0 amper&3.pdf
14/12/2014 00:28 0 hash#1.xls
14/12/2014 00:28 0 hash#2.xls
14/12/2014 00:28 0 hash#3.xls
14/12/2014 00:28 0 LTD LTD 1.pdf
14/12/2014 00:28 0 LTD LTD 2.pdf
14/12/2014 00:28 0 LTD LTD 3.pdf
14/12/2014 00:28 0 lower ltd 1.pdf
14/12/2014 00:28 0 lower ltd 2.pdf
14/12/2014 00:28 0 lower ltd 3.pdf
14/12/2014 00:28 0 ALL#& LTD 1.pdf
14/12/2014 00:28 0 ALL#& LTD 2.pdf
14/12/2014 00:28 0 ALL#& LTD 3.pdf
14/12/2014 00:28 0 shriek!hello!1.pdf
14/12/2014 00:28 0 shriek!hello!2.pdf
14/12/2014 00:28 0 shriek!hello!3.pdf
14/12/2014 00:28 0 pcnt%hello%1.pdf
14/12/2014 00:28 0 pcnt%hello%2.pdf
14/12/2014 00:28 0 pcnt%hello%3.pdf
14/12/2014 00:28 0 co,mm,a1.pdf
14/12/2014 00:28 0 co,mm,a2.pdf
14/12/2014 00:28 0 co,mm,a3.pdf
14/12/2014 00:28 0 se;mi1.pdf
14/12/2014 00:28 0 se;mi2.pdf
14/12/2014 00:28 0 se;mi3.pdf
14/12/2014 00:28 1,074 newfile.txt
32 File(s) 1,074 bytes
2 Dir(s) 2,099,904,512 bytes free
Then this batch:
@ECHO OFF
SETLOCAL
SET "sourcedir=U:\sourcedir\t w o"
PUSHD "%sourcedir%"
(
FOR /f "delims=" %%a IN (
'dir /b /a-d *.pdf *.xls'
) DO (
SET "oname=%%a"
CALL :alter
)
)>newfile.txt
popd
GOTO :EOF
:alter
SET "name=%oname:&=and%"
SET "name=%name:#=%"
SET "name=%name: LTD=%"
ECHO(REN "%oname%" "%name%"
GOTO :eof
Yields, in u:\sourcedir\t w o\newfile.txt
REN "amper&1.pdf" "amperand1.pdf"
REN "amper&2.pdf" "amperand2.pdf"
REN "amper&3.pdf" "amperand3.pdf"
REN "LTD LTD 1.pdf" "LTD 1.pdf"
REN "LTD LTD 2.pdf" "LTD 2.pdf"
REN "LTD LTD 3.pdf" "LTD 3.pdf"
REN "lower ltd 1.pdf" "lower 1.pdf"
REN "lower ltd 2.pdf" "lower 2.pdf"
REN "lower ltd 3.pdf" "lower 3.pdf"
REN "ALL#& LTD 1.pdf" "ALLand 1.pdf"
REN "ALL#& LTD 2.pdf" "ALLand 2.pdf"
REN "ALL#& LTD 3.pdf" "ALLand 3.pdf"
REN "shriek!hello!1.pdf" "shriek!hello!1.pdf"
REN "shriek!hello!2.pdf" "shriek!hello!2.pdf"
REN "shriek!hello!3.pdf" "shriek!hello!3.pdf"
REN "pcnt%hello%1.pdf" "pcnt%hello%1.pdf"
REN "pcnt%hello%2.pdf" "pcnt%hello%2.pdf"
REN "pcnt%hello%3.pdf" "pcnt%hello%3.pdf"
REN "co,mm,a1.pdf" "co,mm,a1.pdf"
REN "co,mm,a2.pdf" "co,mm,a2.pdf"
REN "co,mm,a3.pdf" "co,mm,a3.pdf"
REN "se;mi1.pdf" "se;mi1.pdf"
REN "se;mi2.pdf" "se;mi2.pdf"
REN "se;mi3.pdf" "se;mi3.pdf"
REN "file1.xls" "file1.xls"
REN "file2.xls" "file2.xls"
REN "file3.xls" "file3.xls"
REN "hash#1.xls" "hash1.xls"
REN "hash#2.xls" "hash2.xls"
REN "hash#3.xls" "hash3.xls"
Upvotes: 0
Reputation: 130809
I see 2 major problems:
1) Your REN command must have the full path to the source file. You are providing the name and extension only.
2) It looks like you are attempting to strip out %
characters as well. That cannot be done with normal expansion - delayed expansion is required. Also, the %
must be doubled.
I see a number of inefficiencies:
1) There is no need for any CALL or GOTO. Both are relatively slow. Everything can be done within one loop using parentheses. The performance difference could be significant if there are many files to process. Note that working with variables that have been set within a block requires delayed expansion.
2) Repeatedly opening and closing your log file to append more information is slow. It is more efficient to enclose an entire block within parentheses and redirect only once.
3) You are attempting to remove :
from the name. This is not necessary because Windows file names cannot contain :
.
4) You have already set your current directory to the root, so there is no need to include the path when redirecting.
Here are a few points of note for my untested solution below:
1) Delayed expansion is toggled on and off within the loop to protect any !
that may appear within file names or paths. FOR variables are corrupted upon expansion if they contain !
and delayed expansion is enabled.
2) I used echo(
instead of echo.
to echo a blank line. This syntax looks weird, but it always works. The echo.
synyax can fail under certain obscure conditions.
3) I used PUSHD insead of CD to set the current directory to your root. CD will not work properly without the /D option if you are changing the current volume (D: to C: for example)
4) The outer block redirects a non-standard/unused file handle to the logfile. Then within the block, specific outputs are redirected to the logfile handle. This is done so that the logfile does not have to be repeatedly opened, repositioned to end, and closed. Other outputs go to normal stdout.
@echo off
setlocal disableDelayedExpansion
set /a xcount=0
set "root=c:\clients"
Set "logfile=Changed.txt"
pushd "%root%"
3>"%logfile%" (
for /f "delims=" %%F in ('dir /a:-d /o:n /b /s *.pdf *.xls') do (
set "file=%%~fF"
set "old=%%~nxF"
set "new=%%~nxF"
setlocal enableDelayedExpansion
set "new=!new:&=and!"
set "new=!new:#=!"
set "new=!new: LTD.=!"
set "new=!new:%%=!"
if "!new!" neq "!old!" (
set /a xcount+=1
ren "!file!" "!new!"
echo "!file!" "!new!"
echo !xcount! - "!file!" "!new!">&3
)
endlocal
)
echo(>&3
echo End of file>&3
)
popd
pause
exit /b
Note - The solution above implements the rules as you have stated them. But there is a problem. A name like "Acme LTD.pdf"
would be renamed "Acmepdf"
UPDATE
Since answering, I've written a handy utility called JREN.BAT that can solve the problem very simply. The utility performs rename operations by doing regular expression search and replace on file names. JREN.BAT is a hybrid JScript/batch script that runs natively on any Windows machine from XP onward.
I've refined your rules a bit so that LTD
occurring immediately before the extension preserves the dot for the extension, and LTD.
occurring in the middle of the name removes the dot.
Assuming you have JREN.BAT in your current directory, or better yet, somewhere within your PATH, then the following script should do the trick.
renFiles.bat
@echo off
call jren "(&)|(#|%| LTD(?=\.[^.]*$)| LTD\.)" "$1?'and':''" /i /s /j /fm "*.pdf|*.xls" %1 >rename.log
type rename.log
I recommend running the above in test mode using the /T
option. It will simply list the proposed rename operations without actually renaming anything.
renFiles /T
After verifying everything looks good, then run again without /T
Upvotes: 1