Batch Script to generate multiple command-line instructions - windows

I am writing a batch file Primary.bat which collects all the text file names from a particular directory and pipe the output to Generator.bat
The contents of Primary.bat currently:
#echo off
SETLOCAL=ENABLEDELAYEDEXPANSION
Rem Following command will write the names of all files in a text file
dir /b "C:\InputOutput\SourceFiles" > "C:\InputOutput\Generator.bat"
So, the contents of Generator.bat will be:
input1.txt
input2.txt.
input3.txt
unitedstates1.txt
unitedkingdomsales.txt
majorregion100.txt
Now I need to add code in Primary.bat so that all the above lines gets created in Generator.bat with some additional text as per below:
converter.java C:\InputOutput\SourceFiles\input1.txt C:\InputOutput\OutFiles\input1.rtg
converter.java C:\InputOutput\SourceFiles\input2.txt C:\InputOutput\OutFiles\input2.rtg
converter.java C:\InputOutput\SourceFiles\input3.txt C:\InputOutput\OutFiles\input3.rtg
converter.java C:\InputOutput\SourceFiles\unitedstates1.txt C:\InputOutput\OutFiles\unitedstates1.rtg
converter.java C:\InputOutput\SourceFiles\unitedkingdomsales.txt C:\InputOutput\OutFiles\unitedkingdomsales.rtg
converter.java C:\InputOutput\SourceFiles\majorregion100.txt C:\InputOutput\OutFiles\majorregion100.rtg
Once Primary.bat ran you should then just be able to double-click Generator.bat which will execute all of the commands.
Thanks in advance

There are still some points I don't understand about your code but as far as I understood your task, this should work:
#ECHO OFF
SETLOCAL EnableDelayedExpansion
TYPE NUL>Generator.bat
ECHO #ECHO OFF>>Generator.bat
FOR /F %%F IN ('DIR /B InputOutput\SourceFiles') DO (
ECHO START converter.java "C:\InputOutput\SourceFiles\%%F" "C:\InputOutput\OutFiles\%%~nF.rtg">>Generator.bat
)
As you only want to execute converter.java, you also can skip START. I've suggested START to be able to decide how you want to execute your application (eg. by adding /b or /p or /w or whatever as a parameter for START).

The following should work. Since converter.java is a source file, it can't be executed. I therefore assume you mean java Converter, which will work assuming you have written a class called Converter, placed it in Converter.java, and compiled it with javac Converter.java to create Converter.class.
#echo off
>C:\InputOutput\Generator.bat (for %%f in (C:\InputOutput\SourceFiles\*.txt) do (
echo java Converter "%%f" "C:\InputOutput\OutFiles\%%~nf.rtg"
))

NOTE!! This is assuming that all of the files in the Directory has an .txt extension as per your example
#echo off
if exist "C:\InputOutput\Generator.bat" move /Y "C:\InputOutput\Generator.bat" "C:\InputOutput\Generator.back"
echo #echo off > "C:\InputOutput\Generator.bat"
setlocal enabledelayedexpansion
for /F %%a in ('dir /b C:\InputOutput\OutFiles\') do (
set result=%%a
set renamed=!result:.txt=.rtg!
echo converter.java "C:\InputOutput\SourceFiles\!result!" "C:\InputOutput\OutFiles\!renamed!" >> "C:\InputOutput\Generator.bat"
)
endlocal

Related

Sorting files into folders, according to a part of filename using Windows Batch file

I have around 12,000 .jpg files in a data-set folder in G:\train with names such as
0002_c1s1_000451_03.jpg, 0002_c1s1_000551_01.jpg...
up to
...1500_c6s3_086542_02.jpg , 1500_c6s3_086567_01.jpg
I want to move them to new folders with their initial filename such as 0002, 0005, 0007,... 1496, 1500
What I need is a Windows batch file to create new folders & move files quickly without a hassle. I've tried few other answers to no avail.
Something like this should do, as a .cmd/.bat script file:
#rem The DEBUG_RUN variable enables a step-by-step mode, it will cause the
#rem script to pause after processing every file. Remove the DEBUG_RUN (and
#rem the pause instruction) when you are confident it does what you want,
#rem restart the script and enjoy :-)
:main
#setlocal
#set DEBUG_RUN=1
#pushd "G:\train"
#for %%f in (*.jpg) do #(
call :mvToSubDir "%%~nxf"
if defined DEBUG_RUN pause
)
#popd
#pause
#endlocal
#goto:eof
:mvToSubDir
#set fn=%~1
#set dn=%fn:~0,4%
#if not exist "%dn%" mkdir "%dn%"
move "%fn%" "%dn%"
#goto:eof
you can try a series of for loops to accomplish this
for /l %%f in (1,1,12000) do (
mkdir %%f
for %%d in (c:\sourcedir) do (
move %%d %%f
)
)
i didn't fully understand how you wanted to sort them but i hope this helps. You can use the "for /?" command and feel free to ask for more help if this isn't enough. I wish you luck with your endeavors.

Loop through files in a folder and check if they have different extensions

I have a folder that contains files; each document should have .pdf and .xml format. I need to write a BAT file to run from a scheduled task to verify that both documents exist for each.
My logic is:
loop through files in the folder
strip each file to its name without extension
check that same name files exist for both .xml and pdf.
if not mark a flag variable as problem
when done, if the flag variable is marked, send an Email notification
I know how to use blat to sending email, but I'm having trouble to execute the loop. I found a way to get path and file name without extension but can't merge them.
I've used batch files a few time, before but I'm far from an expert. What am I missing?
Here's the code I have so far:
set "FolderPath=E:\TestBat\Test\"
echo %FolderPath%
for %%f in (%FolderPath%*) do (
set /p val=<%%f
For %%A in ("%%f") do (
Set Folder=%%~dpA
Set Name=%%~nxA
)
echo Folder is: %Folder%
echo Name is: %Name%
if NOT EXIST %FolderPath%%name%.xml
set flag=MISSING
if NOT EXIST %FolderPath%%name%.pdf
set flag=MISSING
)
echo %Flag%
pause
There is no need for fancy code for a task such as this:
#Echo Off
Set "FolderPath=E:\TestBat\Test"
If /I Not "%CD%"=="%FolderPath%" PushD "%FolderPath%" 2>Nul||Exit/B
Set "flag="
For %%A In (*.pdf *.xml) Do (
If /I "%%~xA"==".pdf" (If Not Exist "%%~nA.xml" Set "flag=MISSING")
If /I "%%~xA"==".xml" (If Not Exist "%%~nA.pdf" Set "flag=MISSING")
)
If Defined flag Echo=%flag%
Timeout -1
Something like this :
set "FolderPath=E:\TestBat\Test\"
pushd "%FolderPath%"
for %%a in (*.xml) do (
if exist "%%~na.pdf"(
echo ok
) else (
rem do what you want here
echo Missing
)
)
popd
Is this what you want?
#echo off
setlocal enabledelayedexpansion
set "FolderPath=E:\TestBat\Test\"
echo !FolderPath!
for /f "usebackq delims=" %%f in (`dir !FolderPath! /B`) do (
set /p val=<%%f
For %%A in ("%%f") do (
Set Folder=%%~dpA
Set name=%%~nxA
)
echo Folder is: !Folder!
echo Name is: !name!
if NOT EXIST !FolderPath!!name!.xml set flag=MISSING
if NOT EXIST !FolderPath!!name!.pdf set flag=MISSING
)
echo Flag: !flag!
pause
endlocal
You should reformat your code and keep in mind that the grama for batch file is critical. BTW, if you are trying to update the existing batch variable and read it later, you should enable localdelayedexpansion and use ! instead of %.
Keep it simple:
#echo off
pushd "E:\TestBat\Test" || exit /B 1
for %%F in ("*.pdf") do if not exist "%%~nF.xml" echo %%~nxF
for %%F in ("*.xml") do if not exist "%%~nF.pdf" echo %%~nxF
popd
This returns all files that appear orphaned, that is, where the file with the same name but the other extension (.pdf, .xml) is missing. To implement a variable FLAG to indicate there are missing files, simply append & set "FLAG=missing" to each for line and ensure FLAG is empty initially. Then you can check it later by simply using if defined FLAG.
Note: This does not cover the e-mail notification issue. Since I do not know the BLAT tool you mentioned, I have no clue how you want to transfer the listed files to it (command line arguments, temporary file, or STDIN stream?).
In case there is a huge number of files in the target directory, another approach might be better in terms of performance, provided that the number of file system accesses is reduced drastically (note that the above script accesses the file system within the for loop body by if exist, hence for every iterated file individually). So here is an attempt relying on a temporary file and the findstr command:
#echo off
pushd "E:\TestBat\Test" || exit /B 1
rem // Return all orphaned `.pdf` files:
call :SUB "*.pdf" "*.xml"
rem // Return all orphaned `.xml` files:
call :SUB "*.xml" "*.pdf"
popd
exit /B
:SUB val_pattern_orphaned val_pattern_missing
set "LIST=%TEMP%\%~n0_%RANDOM%.tmp"
> "%LIST%" (
rem // Retrieve list of files with one extension:
for %%F in ("%~2") do (
rem /* Replace the extension by the other one,
rem then write the list to a temporary file;
rem this constitutes a list of expected files: */
echo(%%~nF%~x1
)
)
rem /* Search actual list of files with the other extension
rem for occurrences of the list of expected files and
rem return each item that does not match: */
dir /B /A:-D "%~1" | findstr /L /I /X /V /G:"%LIST%"
rem // Clean up the temporary file:
del "%LIST%"
exit /B
To understand how it works, let us concentrate on the first sub-routine call call :SUB "*.pdf" "*.xml" using an example; let us assume the target directory contains the following files:
AlOnE.xml
ExtrA.pdf
sAmplE.pdf
sAmplE.xml
So in the for loop a list of .xml files is gathered:
AlOnE.xml
sAmplE.xml
This is written to a temporary file but with the extensions .xml replaced by .pdf:
AlOnE.pdf
sAmplE.pdf
The next step is to generate a list of actually existing .pdf files:
ExtrA.pdf
sAmplE.pdf
This is piped into a findstr command line, that searches this list for search strings that are gathered from the temporary file, returning non-matching lines only. In other words, findstr returns only those lines of the input list that do not occur in the temporary file:
ExtrA.pdf
To finally get also orphaned .xml files, the second sub-routine call is needed.
Since this script uses a temporary file containing a file list which is processed once by findstr to find any orphaned files per extension, the overall number of file system access operations is lower. The weakest part however is the for loop (containing string concatenation operations).

Batch Script to Grab File Name and Add to Beginning of Each Line

I'm trying to grab the file name from a .LOG file and append it to the beginning of each line in the file, sans extension, with a space between the file name and the line contents. There are many such files in a folder and the script should be performed for each .LOG file in the folder. An example file name looks like this:
20160201.log
I want to add the file name to each of the lines in the file which look like this:
00:00:23 Left 4EEFD9 6.59418mA 0.00003mA OK
00:00:23 Right 4EEFEF 6.85377mA 0.00001mA OK
00:00:44 Left 4EEFDC 6.32207mA 0.00004mA OK
To give a result of this:
20160201 00:00:23 Left 4EEFD9 6.59418mA 0.00003mA OK
20160201 00:00:23 Right 4EEFEF 6.85377mA 0.00001mA OK
20160201 00:00:44 Left 4EEFDC 6.32207mA 0.00004mA OK
I saw this question here but it references pulling a filename from a list of filenames and placing at the beginning of each entry respectively, so that doesn't work for me. I also looked at this question, but since I need to use the file name instead of my current system time that won't work either. I don't have any code to offer...I couldn't use anything conclusive from the questions I found and I'm totally new to batch scripts.
EDIT 1: Magoo's code
Here is the current code I'm trying to run using Magoo's answer (Note the comments are my addition for troubleshooting):
#ECHO Off
SETLOCAL
SET "sourcedir=C:\Users\ckemmann\Desktop\Current"
SET "destdir=C:\Users\ckemmann\Desktop\Current\New"
::echo %sourcedir% <I check what I've assigned to sourcedir.
::echo %destdir% <And to destdir.
::pause
FOR %%f IN ("%sourcedir%\*.log") DO >"%destdir%\%%~nf.out" (
FOR /f "usebackqdelims=" %%a IN ("%%f") DO (
ECHO %%~nf %%a
)
)
::pause <I catch the batch script telling me that the system cannot find the path specified.
GOTO :EOF
As shown in the code, I get a complaint from windows saying that it can't find the file path...even though that's the one I copied from the folder properties.
EDIT 2:
Since I didn't hear back on my edit 1 I went with Arescet's answer. I sadly don't seem to have any way around the slowness of the script. My final code is the same as what he provided in his answer.
#ECHO Off
SETLOCAL
SET "sourcedir=U:\sourcedir\t w o"
SET "destdir=U:\destdir"
FOR %%f IN ("%sourcedir%\*.log") DO >"%destdir%\%%~nf.out" (
FOR /f "usebackqdelims=" %%a IN ("%%f") DO (
ECHO %%~nf %%a
)
)
GOTO :EOF
You would need to change the settings of sourcedir and destdir to suit your circumstances.
Decoding...
Take the files matching "*.log" from the specified directory, assign their names to %%f
create a new file %%~nf.out in the destination directory. Read each line from %%f to %%a and echo that line, prefixed by %%~nf and a few spaces.
%%~nf means the name part only of %%f.
The redirector > createas a new file and in the position it's been placed, accepts the output of the echo into that file instead of the normal echo-to-console.
#echo off
for /r "C:\PATH TO WHEREVER\" %%G in (*.log) do (
ren "%%~G" "reWrite.temp"
for /f "tokens=*" %%H in (reWrite.temp) do (
echo %%~nG %%H >> %%~nG.log
)
del "reWrite.temp"
)
pause
This takes all .log files in "C:\PATH TO WHEREVER\", renames them, and writes the filename and data line by line into the original name, then deletes the file when done. #Magoo's answer clearly tops mine, but a different solution should help you understand different ways to solve future desires.

Removing a "sample.ext.ext2" file that has no "sample.ext" file associated with it

The application creates .mta files (with exactly same name) of all multimedia files in my HDD. What I want to do is to check all sub-folders of root folder if there is no multimedia file associated with some .mta then delete it.
Detailed example. Lets say we have files
01.mp3
01.MP3.mta
02.mkv
02.MKV.mta
03.jpg
03.JPG.mta
04.MP4.mta <<==
As you see the last .mta has no original file. I want to delete last file.
I don't know if it's possible with cmd. But following function doesn't work. Please take a look
For /r %%i in (*.mta) do call :nomta %%i
pause
goto end
:nomta
set stem=%1:.mta=%
set original=%stem%.mta
if not exist %original% do exit /B
if not exist %stem% do del /a /Q %1
goto :EOF
:end
echo done
PAUSE
You can use a for command to do this with dir /a feeding it both hidden and non-hidden filenames. Here's an example:
C:\temp\z\z>attrib *
A C:\temp\z\z\foo.bar.mta
A H C:\temp\z\z\h2.mp4.mta
A C:\temp\z\z\hid.mp4
A H C:\temp\z\z\hid.mp4.mta
A C:\temp\z\z\zoo.bar
A C:\temp\z\z\zoo.bar.mta
C:\temp\z\z>for /f %F in ('dir /b/a *.mta') do if not exist "%~nF" echo %F >> z
C:\temp\z\z>type z
foo.bar.mta
h2.mp4.mta
so replacing the echo with a del should achieve your target.

batch file to return next to last line of text file

I have a file that contains the output of a file compare thats written to a text file:
Comparing files C:\LOGS\old.txt and C:\LOGS\NEW.TXT
***** C:\LOGS\old.txt
***** C:\LOGS\NEW.TXT
folder_thats_different
*****
I need to pull out the next to last line "folder_thats_different" and put in a new string:
folder contains a file that is different: folder_thats_different
Yes, I know I can use another language, but I'm stuck with batch files for now.
You can try to read it with a for-loop and take the current line, and always save the previous line
#echo off
setlocal EnableDelayedExpansion
for /f "delims=" %%x in (myFile.txt) do (
set "previous=!last!"
set "last=%%x"
)
echo !previous!
Here's an example you can use as a starting point. Just change the filename in the set command= line to the appropriate name (or replace the command with whatever will gerneate the log listing).
#echo off
#setlocal
(set command=type test.txt)
for /f "usebackq tokens=*" %%i in (`%command%`) do call :process_line %%i
echo next to last line: %old_line%
goto :eof
:process_line
(set old_line=%new_line%)
(set new_line=%*)
goto :eof
Of course, you'll probably want to do something other than simply echoing the found line.
The first answer works for me. I also added 2 lines after the end to allow it to repeat so I could watch an active log file without having to close and reopen it. I do a lot of debugging for the mods that are used in the game Space Engineers.
My version looks like this:
#echo off
setlocal EnableDelayedExpansion
for /f "delims=" %%x in (SpaceEngineers.log) do (
set "previous=!last!"
set "last=%%x"
)
echo !previous!
timeout 15 /nobreak
se_log
The line below stops the batch file from looping too fast and stop the key bypass. To change the amount of time in seconds just change the number "15" to anything you want. To stop the batch file just press ctrl+c.
timeout 15 /nobreak
The line below is the name of the batch file I made so it will tell CMD to run this again.
se_log

Resources