I have text file (2.txt) with even number of lines. Odd lines are current names of the files that I need renamed (odd lines contain file extension). Even lines are new names of the corresponding files (even lines DO NOT contain file extension).
E.g. of such file:
001.mp3
First song.
002.mp3
I am a song, too!
003.mp3
He's the one who will rename me...
(end of file)
I want to loop through file, read the line into variable, check if it contains extension (mp3). If yes (odd line), then save it to "name" variable. If not (even line), then save it to "line" variable with dot and extension added to the end (e.g., First song..mp3) and rename "name" file into "line" file. Thus "001.mp3" will be renamed to "First song..mp3".
I tried to combine different parts of the code from different sources, but something goes wrong.
FOR /F "tokens=*" %%i IN (2.txt) DO (
set var=%%i
if not x%var:mp3=%==x%var% set name=%%i
if x%var:mp3=%==x%var% (
set line=%%i.mp3
ren name line
)
)
pause
This is some tricky code. Hopefully you will understand it.
I used this as my 2.txt file
001.mp3
First song
002.mp3
I am a song
003.mp3
last song
004.mp3
my final! song
And here is my code.
#echo off
setlocal enableExtensions enableDelayedExpansion
for /F "tokens=1* delims=:" %%a in ('findstr /N "^" "2.txt"') do set "lines=%%~a"
set /a "lines=lines / 2"
< 2.txt (
for /L %%l in (1, 1, %lines%) do (
set "line1="
set "line2="
set /P "line1="
set /P "line2="
echo rename "!line1!" "!line2!.mp3"
)
)
endlocal
Pause
My output
rename "001.mp3" "First song.mp3"
rename "002.mp3" "I am a song.mp3"
rename "003.mp3" "last song.mp3"
rename "004.mp3" "my final! song.mp3"
Press any key to continue . . .
Remove the ECHO before the rename command if you feel the output on the screen looks good.
Try like this :
#echo off
setlocal enabledelayedexpansion
for /f "delims=" %%a in (2.txt) do (
set "$Line=%%a"
If /i [!$Line:~-4!]==[.mp3] (
set "$FileMp3=%%a"
) else (
echo ren "!$FileMp3!" "%%a.mp3"
)
)
)
If the output is correct remove the echo
Related
I have 5000 .pdf files which I have to rename and to move into newly created folders, whose names are based on the original file names.
For example: original name is crf--aaa--208912--2089120010.
The folder name should be 208912 and the file name 2089120010.
Please help with the process to do so.
You might want to thy the following code snippet:
rem // Change to directory containing the files:
pushd "D:\Data" && (
rem // Retrieve matching files and iterate through them:
for /F "delims=" %%F in ('dir /B /A:-D "*--*--*--*.pdf"') do (
rem // Store name of currently iterated file:
set "NAME=%%F"
setlocal EnableDelayedExpansion
rem /* Split name into tokens separated by `--`; since `for /F` uses characters
rem as delimiters but not strings, `--` is replaced by `|` intermittently: */
for /F "tokens=3* delims=|" %%I in ("!NAME:--=|!") do (
endlocal
rem // Create sub-directory:
mkdir "%%I"
rem // Rename and move file:
move "%%F" "%%I\%%J"
)
endlocal
)
rem // Restore previous working directory:
popd
)
I have the below code which gets the last modified file from "AX copy" and compares it with the last modified file in "Reflex copy". It then outputs the difference in Error.
I need the output copy to have the same name as the input file from "AX copy". I have used something to declare the file name again and assign it to the output. however I have a problem, when delcaring it in the below code, it uses the oldest file name.
Please can someone adjust the code so the output copy has the same name as the input from the "AX copy" folder. My code is:
#echo off
cd /d C:\Users\Important Structure\Development\AX copy
for /f %%a in ('dir /b /o-d /a-d /tw') do (set latest=%%a)
setlocal enableextensions disabledelayedexpansion
call :getLatestFileInFolder "C:\Users\Important Structure\Development\AX copy" latestC
call :getLatestFileInFolder "C:\Users\Important Structure\Development\Reflex copy" latestD
if not defined latestC ( echo NO File in C & exit /b )
if not defined latestD ( echo NO File in D & exit /b )
for /f "tokens=1,*" %%a in (
'diff "%latestC%" "%latestD%" ^| findstr /r /c:"^<" /c:"^>"'
) do (
>> "C:\Users\Important Structure\Development\Error\%latest%" echo(%%b
)
endlocal
exit /b
:getLatestFileInFolder folderToSearch variableToReturn
setlocal
set "folder=%~1" & if not defined folder set "folder=%cd%"
set "latest="
pushd "%folder%"
for /f "tokens=*" %%a in ('dir /b /o-d /a-d /tw 2^>nul') do (set "latest=%%~fa" & goto :latestFileFound)
:latestFileFound
popd
endlocal & set "%~2=%latest%" & goto :eof
In this line
for /f %%a in ('dir /b /o-d /a-d /tw') do (set latest=%%a)
The dir command in listing file in date descending order. On first iteration (the first file), the latest file is assigned to the variable, but for command does not stop here, and continues iterating over the rest of the files. So, at end, the variable contains the oldest file in folder.
To solve it , you can list the files in ascending date order (change /o-d to /od), or use the included subroutine
call :getLatestFileInFolder "C:\Users\Important Structure\Development\AX copy" latest
Which, as the code is working, is the same that Matt has indicated to you. %latest% is the same file that %latestC%
Why does it not work. diff command has to open the file to read, so, probably, you can not write to it while diff has it locked.
To solve it, select a temporary file (set "tempFile=%temp%\%~nx0.tmp"), write the generated diff to this temporary file and then append this temporary file to the original file (type "%tempFile%" >> "%latest%") or overwrite it if the previous content is not needed (type "%tempFile%" > "%latest%")
I need to get a part of some lines(Myfile) out of the 'for' loop either into two separate variables or into an array.My goal is to use each other for constituting path of the following lines result*.txt. I write what you are seing below but it's visible that my 'a' variable is only echoing 'C:\Temp\FR'(the end of line matching token in Myfile).
Please, Is there any way to get all matching tokens in a variable/array? For example, in my case, I need to get 'C:\Temp\USA' and 'C:\Temp\FR' out of the loop for? Thanks
for /f "tokens=2 delims==" %%x in (Myfile) do (
set a=%%x
)
echo %a%
'MyFile
DIR1= C:\Temp\USA
DIR2= C:\Temp\FR
result1.txt
result2.txt
Try this:
#echo off&setlocal
for /f "tokens=1* delims== " %%x in (Myfile) do (
if /i "%%x"=="dir1" set "path1=%%y"
if /i "%%x"=="dir2" set "path2=%%y"
)
echo %path1%
echo %path2%
Output is:
C:\Temp\USA
C:\Temp\FR
There are several ways to do that. If you want read a few lines from the beginnng of the file, the easiest way is to directly read them in a couple variables:
< Myfile (
set /P var1=
set /P var2=
)
Note that these variables contain the complete lines, so it is necessary to extract the part after the equal sign.
In your example you just want the lines with equal sign, so we may use findstr "=" Myfile in a FOR command to just process they. If the number of lines is undefined, you must save all desired lines in an array as you suggested:
setlocal EnableDelayedExpansion
set n=0
for /F "tokens=2 delims==" %%a in ('findstr "=" Myfile') do (
set /A n+=1
set var[!n!]=%%a
)
rem Show all array elements
for /L %%i in (1,1,%n%) do (
echo !var[%%i]!
)
rem Show just the second element
echo %var[2]%
However, in your particular case the lines you want have the form of variable assignments. This means that if you execute such lines with a SET command, the values in the lines will be "automatically" saved:
for /F "delims=" %%a in ('findstr "=" Myfile') do set %%a
After previous FOR , you may directly get the values of DIR1 or DIR2 variables, for example:
echo %DIR1%
echo %DIR2%
This method is very simple and don't require any testing on the individual variables being loaded.
If you want to remove the space after the equal sign in the value, you may adjust FOR options to do so:
for /F "tokens=1* delims== " %%a in ('findstr "=" Myfile) do set %%a=%%b
I have file with a list of names and extensions, formatted such as below each on it's own line:
JoeBloggs=102
JohnSmith=109
What I want to do is use findstr but read the number after the equals sign. So I am using the following command:
#echo off
for /F "delims=" %%a in ('findstr /p %username% extensions.txt') do set ext=%%a
If a user logs on as JoeBloggs it will capture JoeBloggs=102, what I want it to do is only capture 102. So essentially only the numbers after the equals sign.
#echo off
for /f "tokens=1,2 delims==" %%a in (names.txt) do (
if "%%a"=="%username%" set ext=%%b
)
echo %ext%
pause >nul
This will read each line of your text file and split it when it comes across an = sign.
I have specified to use tokens 1 and 2, 1 being before the split, and 2 being after so we can compare the first and if it's what you want, use the second.
searched this site and others - no joy.
:: first for loop
for /L %%x in (1,1,2) do (
generic-executable.output > grab1-%%x.txt
:: second, nested for loop
for /f "delims=" %%i in (grab1-%%x.txt) do (set grab1=%%i)
echo variable string is %grab1%%x%
generic-executable.output > grab2-%%x.txt
for /f "delims=" %%i in (grab2-%%x.txt) do (set grab2=%%i)
echo variable string is %grab2%%x%
)
Trying to run a nested for loop that will
1) write data to the file
2) take data from the file and save it to another variable.
The names of the end variables should be a concatenation of each of the for loops (i.e. grab1-1, 2-1, 1-2, 2-2).
Saving the data to the variables is no problem, formatting the variables to recall the data IS.
I'm most likely missing something in the formatting of the concatenated variable. I've tried single ', double ", ^, !, one %, two %, backslash, ACK!! ... the closest I've gotten is
echo %grab1-%%x
gave:
%grab1-1
I'd appreciate any tips you can provide.
Thanks,
Dave
You have run into a classic stumbling block for batch newbies: You cannot set a variable within a loop (within parentheses) and then access the value using %var% within the same loop. The Entire loop (parenthesized block of code) is parsed in one pass, and %var% is expanded at parse time. So you see the value of var as it was prior to the loop executing.
The solution is to enable delayed expansion using setlocal enableDelayedExpansion near the top of your script, and then expand the variable using delayed expansion as !var!. Delayed expansion means the value is expanded at run time - exactly what you want.
I believe this is what you were trying to achieve
setlocal enableDelayedExpansion
for /L %%x in (1,1,2) do (
genericOutput1.exe > grab1-%%x.txt
for /f "delims=" %%i in (grab1-%%x.txt) do set "grab1-%%x=%%i"
echo grab1-%%x variable string is !grab1-%%x!
genericOutput2.exe > grab2-%%x.txt
for /f "delims=" %%i in (grab2-%%x.txt) do set "grab2-%%x=%%i"
echo grab2-%%x variable string is !grab2-%%x!
)
::List all of the grab variable defined
set grab
You don't need to save the output of your executables to a file. (Unless of course that is your requirement). You can use FOR /F to process the output directly. The FOR command has many variants that look nearly identical, yet behave very differently. This variant uses single quotes to cause FOR /F to process a command.
setlocal enableDelayedExpansion
for /L %%x in (1,1,2) do (
for /f "delims=" %%i in ('genericOutput1.exe') do set "grab1-%%x=%%i"
echo grab1-%%x variable string is !grab1-%%x!
for /f "delims=" %%i in ('genericOutput1.exe') do set "grab2-%%x=%%i"
echo grab2-%%x variable string is !grab2-%%x!
)
::List all of the grab variable defined
set grab
Note that FOR /F will iterate each line (whether it be from a text file or from command output). Your algorithm will only save and print the content of the last line - each successive line will overwrite the value from the prior line.