Batch rename file with variable - batch-file

I try to rename a file with a variable myVar that I have set in the for loop below. The problem is that rename is not working. Can anybody tell me why?
For /F %%A in ('"type tmpFile2.txt"') do set myVar=%%A
ren file1.txt file2%myVar%.txt

I could bet that your code is placed inside parentheses like this one:
if some == comparison (
For /F %%A in ('"type tmpFile2.txt"') do set myVar=%%A
ren file1.txt file2%myVar%.txt
)
If this is the case, you need to use Delayed Expansion in order to get the value of a variable that was modified inside the block:
setlocal EnableDelayedExpansion
if some == comparison (
For /F %%A in ('"type tmpFile2.txt"') do set myVar=%%A
ren file1.txt file2!myVar!.txt
)
For further details, search this or other sites for "delayed expansion".

Hi Please try this code.
for /F "tokens=*" %%i in (myfile.txt) do (
set %filename% = %%i
ren file1.txt file2%filename%.txt
)

Your code is working, maybe the problem is with the tmpfile2.txt content (The token),
or maybe the variable value has spaces and thats the reason why is not working,
without the content of the tmpfile2 we can't know why is not working.
Try this way to see what is happenning:
For /F "delims= usebackq" %%# in ("tmpFile2.txt") do (Echo "myVar=%%#" & set "myVar=%%#")
Echo Rename "file1.txt" "file2%myVar%.txt"
Rename "file1.txt" "file2%myVar%.txt"
Or this else:
For /F "delims= usebackq" %%# in ("tmpFile2.txt") do (Rename "file1.txt" "file2%%#.txt")

Related

How to insert a revision number in string

I’m using the following script to add a revision number to a .stp file. For example: ABS0012033.stp to ABS0012033_rev001.stp. This is working well.
Now I have some files that end with _asm.stp, for example, ABS0012033_asm.stp. How do I need to modify the script that it works for both file types?
Some additional information: There is only one .stp file to be renamed per time and then the .stp file will be moved to another folder. The text file which contains the revision number is temporary and will be deleted after renaming the .stp file.
The current script does remove the last 4 characters from the filename and stores the filename in variable str1. Then it renames the filename with str1 + revision number.
for /F "usebackq tokens=2" %%a IN (`findstr REVISION C:\PUBLISH_WORKSPACE\*.txt`) do (
SET Rev=%%a)
FOR %%S IN ( c:\publish_workspace\*.STP) DO (SET FILE=%%S)
set str1=%file:~21,-4%
ren %file% %str1%_rev%REV%.stp
EXIT
I have tried to implement an IF function in the following script, but it doesn’t work. It doesn’t write str1 when renaming the filename. Any ideas what the problem could be?
for /F "usebackq tokens=2" %%a IN (`findstr REVISION C:\PUBLISH_WORKSPACE\*.txt`) do (
SET Rev=%%a)
FOR %%S IN ( c:\publish_workspace\*.STP) DO (SET FILE=%%S)
echo.%FILE%|findstr /C:"_asm" >nul 2>&1
if not errorlevel 1 (
set str1=%file:~21,-8%
ren %file% %str1%_rev%REV%.stp
) else (
set str1=%file:~21,-4%
ren %file% %str1%_rex%REV%.stp
)
pause
move c:\publish_workspace\*.stp c:\publish_workspace\stp
del c:\publish_workspace\*.txt
EXIT
Sorry, I'm not sure to understand the problem. What about this?
set Rev=ren001
ren ABS???????_asm.stp ABS???????_%Rev%.stp
This answer makes assumptions, those assumptions could have been resolved had you responded to my comment one day ago.
#Echo Off & SetLocal EnableExtensions
PushD "C:\Publish_Workspace" 2>NUL && (Set "Rev=") || GoTo :EOF
For /F "Tokens=1,* Delims=:" %%G In ('%SystemRoot%\System32\findstr.exe "REVISION" "*.txt"') Do Set "Rev=%%H"
If Not Defined Rev GoTo :EOF
For /F Delims^=^ EOL^= %%G In ('Set "PathExt=" ^& %SystemRoot%\System32\where.exe ".":"*.stp" 2^>NUL') Do For /F Delims^=_^ EOL^= %%H In ("%%~nG") Do Ren "%%G" "%%H_rev%Rev:* =%%%~xG"
I am not a tutor, and will not be providing additional explanation, other than to refer you to my comments, and the built-in help information for each command, (commandName /?).

Find a string into each file of a folder with for loop

I try to find a string "blabla" inside a file. If I find the string I replace it with "bloblo", if not do nothing. And I want to do this operation for all the files that I have in a folder.
When I apply the script on one file, it works well. When I use a for loop it doesn't work. it does not enter inside the for loop
Here is my script:
set "Var1=blabla"
set "Var2=bloblo"
FOR %%i IN (C:\Users\UserName\Desktop\TEST\*.txt) DO (
find /c "%Var1%" %%i
if %errorlevel% equ 1 goto notfound
call PathFile\FUNCTION_REPLACE.cmd %Var1% %Var2% %%i
:notfound
)
I use a script "Function_replace" to replace the values, here is the script:
SetLocal EnableExtensions DisableDelayedExpansion
Set "search=%~1"
Set "replace=%2"
Set "File=%3"
For /F "Tokens=1*Delims=]" %%A In ('Find /V /N ""^<"%File%"^&Break^>"%File%"'
)Do (Set "line=%%B"
SetLocal EnableDelayedExpansion
(If Not "%%B"=="" (Echo(!line:%search%=%replace%!)Else Echo()>>"%File%"
EndLocal)
I used to use directly the call of my replace function for each files of my folder. But it takes a long time to go inside each file. That's why I want to check before going inside each file, if the string exists or not (by using find /c).
Can you spot where is the issue coming from?
Based upon your latest edit, here's an example which sends only the files containing the string to be replaced, to the sub-function:
#Echo Off
SetLocal EnableExtensions DisableDelayedExpansion
Set "search=%~1"
Set "replace=%~2"
For /F Delims^=^ EOL^= %%A In ('FindStr /LIMP "%search%" *.*')Do Call :Sub "%%A"
GoTo :EOF
:Sub
Set "File=%~1"
For /F "Tokens=1*Delims=]" %%A In ('Find /V /N ""^<"%File%"^&Break^>"%File%"'
)Do (Set "line=%%B"
SetLocal EnableDelayedExpansion
(If Not "%%B"=="" (Echo(!line:%search%=%replace%!)Else Echo()>>"%File%"
EndLocal)
Please note that the FindStr command uses only example options, whilst the /M option is important to this solution you should check the output from FindStr /? to determine which of the others you would consider the most appropriate.
Why not simply list all files that has the string and exclude the files that don't? That seems like a more obvious plan to me:
#echo off
set "search=blabla"
for /f "delims=" %%i in ('findstr /m %search% "%USERPROFILE%\Desktop\TEST\*.txt"') do (
echo found "%search%" in "%%~fi"
)
If you want to still show files that does not contain the path, then #stephan already posted a comment on how to, no need for me to repeat.

Batch folder creation based on part of file name, without keeping extension

Trying to create a script that will take the third token of a file name, create a folder based on it and move the associated file to that folder.
Have got this so far:
#ECHO OFF
SETLOCAL
SET "sourcedir=D:\Sourcedir"
PUSHD %sourcedir%
FOR /f "tokens=1,2,3,4 delims=" %%a IN (
'dir /b /a-d "*.pdf"'
) DO (
ECHO MD %%c
ECHO MOVE "%%a %%b %%c %%d" .\%%c\
)
POPD
GOTO :EOF
Only problem is the folder being created is including the file extension where as I just need the folder to be named the third token.
Example file name:
"File Number 10.pdf
Expected folder name:
10
Thanks
Why did you use delims=? This will remove delimiter, and take whole line to %%a.
Try this:
#ECHO OFF
SETLOCAL
SET "sourcedir=D:\Sourcedir"
PUSHD %sourcedir%
FOR /f "tokens=1,2,3" %%a IN (
'dir /b /a-d "*.pdf"'
) DO (
ECHO MD %%~nc
ECHO MOVE "%%a %%b %%c" .\%%~nc\
)
POPD
GOTO :EOF
When no delims= set, it will use space. So %%c will be 10.pdf, ~n is to extract its name part.
This is based on your question, which you can concatenate %%a %%b %%c together with spaces, then it's simple.
If your filenames are more complicated, then an inner for loop is better.
-- Which another question already gave a great solution.
Here's an alternative, which will just use the last space delimited string/number, regardless of how many there are, (if there are none it will use the whole filename)!
#Echo Off
For %%A In ("D:\Sourcedir\*.pdf") Do Call :L "%%A"
Exit /B
:L
Set "F=%~n1"
Set "F=%F: ="&Set "F=%"
If Not Exist "%~dp1%F%\" MD "%~dp1%F%"
Move /Y %1 "%~dp1%F%"
And if you wanted to move only those which have at least one space, you can include that inside the For parentheses.
#Echo Off
For %%A In ("D:\Sourcedir\* *.pdf") Do Call :L "%%A"
Exit /B
:L
Set "F=%~n1"
Set "F=%F: ="&Set "F=%"
If Not Exist "%~dp1%F%\" MD "%~dp1%F%"
Move /Y %1 "%~dp1%F%"
You can run 2 for loops get the full name in the first, then split the name in the second loop, get the 3rd token, create the directory and then copy the actual file name from the first loop.
This way you do not need to try and patch the name together again, I know it works, but it is ugly and not prefered:
#echo off
setlocal enabledelayedexpansion
set "sourcedir=D:\Sourcedir"
pushd %sourcedir%
for %%a in (*.pdf) do (
set "var=%%a"
for /f "tokens=3" %%i in ("!var!") do (
echo md "%%~ni"
echo move "%%~a" "%%~ni"
)
)
popd
goto EOF
For more information on these commands, see help for each from cmd.exe i.e
for /?
set /?
setlocal /?
set and setlocal has very specific information regarding delayed expansion.

Batch file to rename text files within directory with text from within text file at specific line except if line blank

#Echo off&SetLocal EnableExtensions EnableDelayedExpansion
cd "C:\Documents and Settings\John\Desktop\New\Interest\f2"
Pushd "C:\Documents and Settings\John\Desktop\New\Interest\f2"
Set Line#=26
Set /A LOfs=24 -1, Len=34 - LOfs
For %%A in (*.txt) do For /F "tokens=1* delims=:" %%B in (
'Findstr /N ".*" "%%A" ^|Findstr "^%Line#%:"'
) do if %errorlevel% == 0 Set "Line=%%C"&Ren "%%~fA" "!Line:~%LOfs%,%Len%! - %%A!""
Popd
In the above I am trying to change the filename of files in a directory with text in it at a certain position.
If line 26 is blank do nothing and do not change filename.
I have gone wrong somewhere and am going round in circles.
Can anyone help?
Thank you.
You don't state how your script fails, but I can see some potential problems. I also see possible simplifications.
You certainly don't need both CD and PUSHD
I got rid of the numeric variables and included the number literals in the actual code. You can revert back to variables if you want.
You don't need the outer FOR loop. FINDSTR can search multiple files when using wildcards in the file name, and then it will include the filename, followed by : in the output. So if you add the /N option, output will have the form filename:line#:text. You can then adjust the 2nd FINDSTR to return only the correct line numbers.
It is not enough to ignore blank lines. Your rename only works if there is at least one valid file name character after the 23rd character. Filenames cannot include :, *, ?, /, \, <, >, or |. (I may have missed some). I adjusted the FOR /F delims and the FINDSTR search to compensate.
FOR variable expansion like %%A will corrupt values if they contain ! and delayed expansion is enabled. ! is a valid character in file names. So the delayed expansion must be toggled on and off within the loop.
I believe the following will do what you want. The code below will simply echo the rename commands. Remove the ECHO before the ren once it gives the correct results.
#echo off
setlocal disableDelayedExpansion
pushd "C:\Documents and Settings\John\Desktop\New\Interest\f2"
for /f "tokens=1,3 delims=:*?\/<>|" %%A in (
'findstr /n "^" "*.txt" ^| findstr "^[^:]*:26:.......................[^:*?\\/<>|]"'
) do (
set "old=%%A"
set "line=%%B"
setlocal enableDelayedExpansion
ECHO ren "!old!" "!line:~23,11! - !old!"
endlocal
)
popd
An slightly different method to Daves:
#Echo Off
Set "SrcDir=%UserProfile%\Desktop\New\Interest\f2"
Set "Mask=*.txt"
Set "Line#=26"
Set "LOfs=23"
Set "Len=11"
If /I Not "%CD%"=="%SrcDir%" Pushd "%SrcDir%"2>Nul&&(Set _=T)||Exit/B
For /F "Tokens=1-2* Delims=:" %%A In ('FindStr/N "^" "%Mask%" 2^>Nul'
) Do If "%%B"=="%Line#%" If Not "%%~C"=="" (Set "Line=%%C"
SetLocal EnableDelayedExpansion
If Not "!Line:~%LOfs%,%Len%!"=="" (
If Not Exist "!Line:~%LOfs%,%Len%! - %%A" (
Ren "%%A" "!Line:~%LOfs%,%Len%! - %%A"))
EndLocal)
If "_"=="T" PopD
This method don't require findstr.exe nor toggle setlocal/endlocal, so it should run faster. Also, it avoids to re-process any already renamed file changing the plain for %%A by a for /F combined with dir command.
#Echo off
SetLocal EnableDelayedExpansion
cd "C:\Documents and Settings\John\Desktop\New\Interest\f2"
Set /A Line#=26, LOfs=24 -1, Len=34 - LOfs
For /F "delims=" %%A in ('dir /A-D /B *.txt') do (
rem Read the desired line from this file
(for /L %%i in (1,1,%Line#%) do set "Line=" & set /P "Line=") < "%%A"
if defined Line ECHO Ren "%%~fA" "!Line:~%LOfs%,%Len%! - %%A"
)
Note also that when this Batch file ends the current directory is automatically recovered to the current one when setlocal command was executed, so pushd/popd commands are not needed either.

Batch FOR /F loop won't read relative directory

I have a simply FOR /F loop which strips out all but one line of a text file:
for /f "skip=12 tokens=* delims= " %%f in (.\NonProcessed\*.txt) do (
> newfile.txt echo.%%f
goto :eof
)
But when I run, I get the result:
The system cannot find the file .\NonProcessed\*.txt
The for loop works fine if I enter a fully qualified path to the text file within the brackets, but it can't handle the relative link I have in there. I've been able to use the exact same relative link in another standard for loop in a different batch file running in the same directory without any issues. I can't understand why it won't work! Please help.
EDIT: For comments, code I'm using now is
for %%f in (.\NonProcessed\*.txt) do (
echo f is %%f
for /f "usebackq skip=12 tokens=* delims= " %%a in (%%f) do (
echo a is %%a
> %%f echo.%%a
goto :continue
)
:continue
sqlcmd stuff here
)
Sorry but for /f does not allow you to do that. And no, the problem is not the relative path to files but the wildcard.
According to documentation, you have the syntax case
for /F ["ParsingKeywords"] {%% | %}variable in (filenameset) do command [CommandLineOptions]
For this case, documentation states The Set argument specifies one or more file names. You can do
for /f %%a in (file1.txt file2.txt file3.txt) do ...
but wildcards are not allowed.
If you don't know the name of the file you want to process, your best option is to add an additional for command to first select the file
for %%a in (".\NonProcessed\*.txt"
) do for /f "usebackq skip=12 tokens=* delims= " %%f in ("%%~fa"
) do (
> newfile.txt echo(%%f
goto :eof
)
When executed, the goto command will cancel both for loops so you end with the same behaviour you expected from your original code.
edited to adapt code to comments
#echo off
set "folder=.\NonProcessed"
pushd "%folder%"
for /f "tokens=1,2,* delims=:" %%a in (
' findstr /n "^" *.txt ^| findstr /r /b /c:"[^:]*:13:" '
) do (
echo Overwrite file "%%a" with content "%%c"
>"%%a" echo(%%c
)
popd
Read all the files in the folder, numbering the lines. The output for the first findstr command will be
filename.txt:99:lineContents
This output is parsed to find the line 13, the resulting data is splitted using the colon as a separator, so we will end with the file name in %%a, the line number in %%b and the line content in %%c.
SET FILES_LIST=files_list.config
DIR /b .\NonProcessed\*.txt>!FILES_LIST!
for /f "skip=12 tokens=* delims= " %%f in (!FILES_LIST!) do (
> newfile.txt echo.%%f
goto :eof
)
IF EXIST "!FILES_LIST!" DEL "!FILES_LIST!"
I did not check how your's FOR works, just added my additions/corrections to it.... Hope it will work for you.
Best regards!

Resources