Modifying For loop variables cmd - batch-file

Thing I want to do is to filter out specific video file extensions from a text file containing various video file names e.g filename.txt contents are
Red.mp4
Yellow.mp4
Blue.mp4
Orange.wmv
Purple.wmv
Now I will parse this file for .mp4 only & utilise 'for parameter' to make several .txt files each containing particular code for a particular file. In other words will create number of files same as number of .mp4 video in filename.txt My code
::==
#echo off
setLocal EnableDelayedExpansion
for /f "tokens=* delims= " %%a in ('type filename.txt ^|findstr ".mp4"') do (
set /a n+=1
echo >myfile!n!.txt
set v!n!=x264 --crf 23 --level 3.1 --tune film --o "%%a" "%%a.mkv"
)
set v
pause
::==
I have two problems:
How do I modify %%a to have its .mp4 string removed because when I apply "%%a.mkv" a file will be named *.mp4.mkv and I don't want that and .mp4 can be typed manually like --o "%%a.mp4" "%%a.mkv"
Provided that required txt files are already created how do I pass variables v1,v2,v3... to its respective text file I tried with
echo %v!n!% > >myfile!n!.txt
within loop but it didn't work, so plz advice

I don't see any need to create an array of variables with one loop, and then add the content to files in a 2nd loop. Simply do everything in one loop.
Also, there is no need to create an empty file, and your attempt to do so is incorrect - it adds the line ECHO is off. to each file. To echo a blank line you should use >filename ECHO(. To create an empty file use copy nul filename.
This is unlikely to be a concern, but it is possible for a filename to contain !. Expansion of a FOR variable containing ! will be corrupted if delayed expansion is enabled. The issue can be solved by toggling delayed expansion on and off within the loop, but there is another solution: use another FINDSTR command to prepend each line with the line number, and then parse the line number and file name with the FOR loop. This eliminates the need to increment a counter and eliminates the need for delayed expansion.
The ~n FOR variable modifier is used to get the name without the extension.
#echo off
for /f "tokens=1* delims=:" %%A in (
'findstr /lie ".mp4" filename.txt^|findstr /n "^"'
) do (
>"myfile%%A.txt" echo x264 --crf 23 --level 3.1 --tune film --o "%%B" "%%~nB.mkv"
)

Related

Batch script Read multi line Argument in Variable

I wanted to take list of files to delete from user as a argument. One line per argument.
How can store the list of files separated by new line in a variable.
I am using below command.
Set DeletionFiles=${p:DeleteFiles}"
for %%i in (%DeletionFiles%) do (
echo %%i
)
Then i wanted to iterated them on a loop.
${p:DeleteFiles} will get replaced by it's value from external app, which will contain list of files separated by new line.I can not change it.
#ECHO OFF
SETLOCAL
SET "deletionfiles="
:dloop
SET "deleteme="
SET /p "deleteme=Which file to delete ? "
IF DEFINED deleteme SET "deleteme=%deleteme:"=%"
IF DEFINED deleteme SET "deletionfiles=%deletionfiles%,"%deleteme%""&goto dloop
ECHO delete %deletionfiles:~1%
GOTO :EOF
There is no need to use a newline. Your for command (or a del command) will operate perfectly happily on a comma-(or space-)separated list.
Note that there are certain characters that batch uses for special purposes and batch string-processing may not process them in the expected manner. These characters include % ^ and &.
${p:DeleteFiles} will get replaced by it's value from external app,
which will contain list of files separated by new line.I can not
change it.
After the replacement the batch file looks like:
Set DeletionFiles=file1.jpg
file2.jpg
file3.jpg
"
This isn't a valid batch file anymore.
Furthermore it's a bad idea to modify the batch file itself, as this works only once.
You could place the ${p:DeleteFiles} into another file, like input.txt.
Your batch would look like
echo ${p:DeleteFiles} > input.txt
<external program for replacing the DeleteFiles> input.txt
for /F "tokens=*" %%A in (input.txt) do (
echo File: %%A
)
If I understand you correctly, your external program will generate a list of files. You then want to store this multi-line list to a variable. What do you want to do with the variable once you have it? I assume you want to delete the files, but your question isn't clear on that point, so I'll try to over-answer to cover it.
for /f "delims=" %%a in ('{command that generates your list}') do (
echo Doing stuff to %%a...
echo %%a>>listOfFilesToDelete.txt
set var=%%a
if "%var:~0,7%"="DoNotDelete" copy "%%a" \someArchiveFolder\
del "%%a"
)
This will read each line in your generated list as variable %%a. It will then do whatever command(s) you specify. This way, you can run a command on each of the files in the list. In the above code it's
Printing each line to the console embedded in some text
Outputting it to a file
Checking the first 7 characters of the line against a specified string and then copying it to a folder if it matches
And then deleting it
If you still need to reference each line from your generated list, you can even setup an array-like structure. (See Create list or arrays in Windows Batch)
setlocal EnableDelayedExpansion
:: Capture lines in an 'array'
set /a i=0
for /f "delims=" %%a in ('dir /b') do (
set /a i+=1
set var!i!=%%a
)
:: Loop through the 'array'
for /L %%a in (1,1,%i%) do (
echo Do more stuff with !var%%a!
)
Just like above, this will read each line in your generated list as variable %%a. It will then set a variable var!i! equal to the value of the current line. You can then reference each line as var1, var2, and so on, or, as the second section shows, you can loop through them all using for /L. You'll need to get a grasp on working with delayed expansion variables, though.

Splitting CSV files on specific text

I have got a system that generates CSV files containing time based data.
Some files have data from two different dates. I want to break up these files into two files, one containing the data from the first day, the other containing the data from the next day. The original file looks like this:
09.01.2015 00:00:00,0385 - Veerhaven,VP01 in bedrijf hoog toerental,K,Process message.
09.01.2015 00:00:00,0385 - Veerhaven,VP01 in bedrijf laag toerental,G,Process message.
08.01.2015 23:59:55,1475 - Schaatsbaan,PO01 in bedrijf,G,Process message.
08.01.2015 23:59:52,0311 - Abraham van Stolkweg,PO01 in bedrijf,G,Process message.
The first 10 Characters are the date of the event. I want to break up the file in two output files seperating the data from the two days. I have to do this using batch processing because it has to be done every day over a lot of files.
I hope someone can help me on my way. Thanks in advance.
#echo off
setlocal enableextensions disabledelayedexpansion
set "file=c:\somewhere\data.txt"
for %%f in ("%file%") do for /f "usebackq" %%a in ("%%~ff") do (
if not defined %%a (
findstr /b /c:"%%a" "%%~ff" > "%%~dpnf.%%a%%~xf"
set "%%a=1"
)
)
The first for command is used only to retrieve a reference to the file and being able to separate path, filename and extension (that will be used later to generate the output files).
Second for loop reads the input file and for each line retrieves the first token/field in the line using spaces as delimiters (the default behaviour in for /f command). This value is used to filter the input file and declare environment variables:
If the variable is not defined, it is the first time the value is seen, matching records are extracted from the input file to a new output file and the variable is defined.
If the variable is defined, this value has been seen and the corresponding output file generated, the extraction is skipped and the process continues reading the next line.
edited to adapt to comments
#echo off
setlocal enableextensions disabledelayedexpansion
set "files=c:\somewhere\*.txt"
set "outputFolder=c:\where\to\put\files"
for %%f in ("%files%") do (
setlocal
for /f "usebackq" %%a in ("%%~ff") do if not defined %%a (
findstr /b /c:"%%a" "%%~ff" > "%outputFolder%\%%~nf.%%a%%~xf"
set "%%a=1"
)
endlocal
)
The wildcard management in the input needs no changes: for %%f iterates over the indicated set, being it only a file or a set of files.
The output folder is stored in a environment variable. The redirection is changed to use the variable insted of the path of the input file.
As the variables used to determine if the indicated token has been processed needs to be deleted for each file processed, the loop that processes the file contents is wrapped in a pair of setlocal/endlocal that cleans the flag variables after each file has been processed
read HELP FOR to learn how to use the FOR command to loop over the lines of a file and parse its contents. Then, try
for /f "tokens=1,*" %%a in (timedata.txt) do (
echo %%a ... %%b
)
you see that you may use %%a to split the files by date, so you could figure out something like
for /f "tokens=1,*" %%a in (timedata.txt) do (
echo %%b >>timedata.%%a.txt
)
or more generically
set fn=%~dpn1
set fx=%~x1
for /f "tokens=1,*" %%a in (%~1) do (
echo %%b >>%fn%.%%a%fx%
)

Batch - Looping in 'FileNames_Constant.Ext' , and Print 'FileNames' as an Output

I've got some *.Xml files in a directory and its sub-directories. I need to loop through the XML files which have a specific constant at the end of their file name, and then echo/print their names without the constant part nor the extension (.Xml).
For example: these are the file names I have:
FileAAA_Constant.Xml
FileBBB.Xml
FileCCC.Xml
FileDDD_Constant.Xml
And this is the output I need:
FileAAA
FileDDD
I've tried this command:
For /R %%X in (*_Constant.Xml) do echo %%~nX
Which outputs this:
FileAAA_Constant
FileDDD_Constant
As you can see, it has removed the extension only, while I need to remove "_Constant.Xml" as well.
This works if the file names contains only one underscore, as indicated in your example:
for /F "delims=_" %%X in ('dir /S /B *_Constant.Xml') do echo %%X
If the desired file names may contain more than one underscore, use Pokechu22's answer.
Fairly easy if the exact length of the phrase is known; you just need to use the %var:~0,-3% syntax. Since "_Constant" is 9 chars long, you would want %var:~0,-9%, which takes text from the start (0) to 9 chars from the end (-9). Aditionally, delayed variable expansion also must be enabled with setlocal ENABLEDELAYEDEXPANSION for this to be run inside of your For loop.
Here's a full example:
#Echo off
setlocal ENABLEDELAYEDEXPANSION
for /R %%X in (*_Constant.Xml) do (
set FileNameTemp=%%~nX
echo !FileNameTemp:~0,-9!
)
Note that if you have a file named just _Constant.xml, this will produce "ECHO is off." rather than "" (no output). This can be solved by changing echo !FileNameTemp:~0,-9! to echo. !FileNameTemp:~0,-9!, but that puts a space before each output.
Here's the loop alone:
for /R %%X in (*_Constant.Xml) do (
set FileNameTemp=%%~nX
echo !FileNameTemp:~0,-9!
)

How to concatenate multiple lines of log file into single variable in batch file?

I have a log file containing a stack trace split over a number of lines. I need to read this file into a batch file and remove all of the lines breaks.
As a first step, I tried this:
if exist "%log_dir%\Log.log" (
for /F "tokens=*" %%a in ("%log_dir%\Log.log") do #echo %%a
)
My expectation was that this would echo out each line of the log file. I was then planning to concatenate these lines together and set that value in a variable.
However, this code doesn't do what I would expect. I have tried changing the value of the options for delims and tokens, but the only output I can get is the absolute path to the log file and nothing from the contents of this file.
How can I set a variable to be equal to the lines of text in a file with the line breaks removed?
If you want to use quotes for your filename in the FOR/F loop you need to add the usebackq option too, else you get a string not the content of your file.
for /F "usebackq delims=" %%a in ("%log_dir%\Log.log") do #echo %%a
Or remove the quotes
if exist "%log_dir%\Log.log" (
for /F "tokens=*" %%a in (%log_dir%\Log.log) do #echo %%a
)

Rename multiple images in a folder using a batch file

I have a folder full of images which have a format filename.com_XXX_IMG_000.jpg. The issue comes because the file name has a .com in it, it confuses the the software that I am using to upload it to a webspace.
I need to create a batch file that gets all the images in a folder and renames all of them from filename.com_XXX_IMG_000.jpg => filename_XXX_IMG_000.jpg.
Any help would be greatful, thanks in advance.
Since you want to do it in a batch file:
#echo off
for /f "delims=. tokens=1,2,3" %%f in ('dir /b *.jpg') do (
setlocal enabledelayedexpansion
set part=%%g
if "!part:~0,3!"=="com" (
set oldname=%%f.%%g.%%h
set newname=%%f.!part:~4!.%%h
echo "!oldname!" -^> "!newname!"
ren "!oldname!" "!newname!"
)
endlocal
)
A few notes
for loop variables are single letter, like this: %f
in a batch file, the % must be escaped, so %f becomes %%f
delims=. splits the filenames at the ., in your case into three parts
tokens=1,2,3 returns three variables containing the individual name parts (%f, %g and %h)
enabledelayedexpansion switches on dynamic variable handling
you can do string manipulation with variables: %foo:~0,3% returns the first three characters of %foo%.
with delayed expansion enabled, you can access variables that change their values by using ! instead of %
the > must be escaped or echo won't print it, hence ^>
read some more on String Manipulation in DOS
read HELP FOR and try the following....
#echo off
setlocal enabledelayedexpansion
for %%a in (*.jpg) do (
set fn=%%~na
set fn=!fn:.com=!
echo REN "%%a" "!fn!.jpg"
)
you need to enable delayed expansion because you need to expand a variable inside the for loop.
the loops iterates over all the jpg files in the current directory and for each file it extracts its filename using the ~n syntax, and then it removes all the occurences of .com by replacing them with an empty string. Read HELP SET
after careful testing, remove the echo command

Resources