The purpose is to scan a given folder for media files are send the mediainfo to info.txt BUT also to giv user an option to scan only for files having a particular text string.
My bat file:
Though the first part of if loop works correctly but the 'else' part don't, I can't get the error because with a flicker of an eye it disappears & I can't troubleshoot itCode:@echo off setLocal EnableDelayedExpansion echo. >info.txt set /P "folder=Enter folder path: " set /P "_input=Search all files (y/n): " if /I "%_input%" == "y" ( dir %folder% /B /O:N | findstr /I ".wmv$ .mpg$ .mkv$ .mpeg$ .mp4$ .avi$" >filename.txt for /f "tokens=* delims= " %%a in ('type filename.txt') do ( set _in=%_in%%%a mediainfo --Inform=file://template.txt "%folder%!_in!" >>info.txt echo. >>info.txt ) ) else ( set /P "_str=Enter file string: " dir %folder% /B /O:N | findstr /I "%_str%" >filename.txt for /f "tokens=* delims= " %%a in ('type filename.txt') do ( set in=%in%%%a mediainfo --Inform=file://template.txt "%folder%!in!" >>info.txt echo. >>info.txt ) ) del filename.txt cls pause
+ Reply to Thread
Results 1 to 10 of 10
-
-
CMD's behavior with nested commands can seem erratic at times. It gets more difficult to predict an outcome when external commands are involved.
The old COMMAND ability to execute a batch line by line is sorely missing in CMD. One way to get to see error messages as they appear is to add a pause where you think the problem occurs. In your case you could just REM out the CLS.
When troubleshooting more complex batches, I will open a CMD prompt and copy and execute each line one at a time. That makes it easy to see where to place the line breaks in nested commands. Also, issuing a SET followed by PAUSE, will let you see what your variables are doing.
Ultimately, I find that it's preferable to use subroutines instead. In your case, it's just a matter of choosing the right thing to use IF with:
Code:@echo off setLocal EnableDelayedExpansion echo. >info.txt set /P "folder=Enter folder path: " set /P "_input=Search all files (y/n): " if /I "%_input%" == "y" set _str=.wmv$ .mpg$ .mkv$ .mpeg$ .mp4$ .avi$ if not /I "%_input%" == "y" set /P "_str=Enter file string: " dir %folder% /B /O:N | findstr /I "%_str%" >filename.txt for /f "tokens=* delims= " %%a in (filename.txt) do ( set in=%in%%%a mediainfo --Inform=file://template.txt "%folder%!in!" >>info.txt echo. >>info.txt ) del filename.txt cls pause
-
It's nice to talk about subroutines, but I guess an example would have been nice.
Code:@echo off goto :START :INFO mediainfo --Inform=file://template.txt "%folder%!%%1!" >>info.txt echo. >>info.txt goto :EOF :START setLocal EnableDelayedExpansion echo. >info.txt set /P "folder=Enter folder path: " set /P "_input=Search all files (y/n): " if /I "%_input%" == "y" set _str=.wmv$ .mpg$ .mkv$ .mpeg$ .mp4$ .avi$ if not /I "%_input%" == "y" set /P "_str=Enter file string: " dir %folder% /B /O:N | findstr /I "%_str%" >filename.txt for /f "tokens=* delims= " %%a in (filename.txt) do CALL :INFO %%a del filename.txt cls pause
-
-
To find out what a CMD shell command does, type the "command /?" at the prompt i.e. CALL /? You can also use this site as a reference.
CALL is used to basically put the current batch file on hold while an external command is being executed then to return to the calling batch file at the point where call was issued. In CMD, CALL can also be used with LABELS, so you can run a batch inside the batch and return to where you left off.
Here CALL says go to LABEL :INFO at the beginning of the batch file; %%a is the variable you defined in your FOR statement. The lines after :INFO are executed as if a new batch was being run, thus the value of %%a is read and understood to be the same as %1 in the mediainfo line.
Think of the lines between :INFO and goto :EOF at the beginning of the file as a separate batch file. The FOR statement calls that batch with the value of %a as an argument. To that new batch it's like %a never existed, but arguments following a batch are recognized by the numerical variables %1, %2...
GOTO :EOF means goto end of file. It's required when CALLing a LABEL to tell CMD that the "virtual batch file" ends here. It delimits the subroutine and causes it to exit back to where it was called from.
GOTO :EOF always goes to the end of a batch; it's handy to end a batch without having to define a LABEL.Last edited by nic2k4; 1st Nov 2012 at 21:03.
-
@nic2k4
Thnx for explaining but i am afraid thr are at least three things not right wth the script u gave:
- Under win732bit whole of the script is breaking if i use if not
- If a folder has three files Red,Green,Blued the output of ur script is such that its printed 3 times:
Code:File is: Blued.avi Format: AVI VideoFormat: MPEG-4 Visual CodecID: XVID Resolution: 512x384 DAR: 4:3 or 1.333 PAR: 1.000 FrameMode: VideoBitrateMode: ScanType: Progressive AudioCodec: MPEG Audio AudioBitrateMode: CBRFile is: Green.avi Format: AVI VideoFormat: MPEG-4 Visual CodecID: XVID Resolution: 512x384 DAR: 4:3 or 1.333 PAR: 1.000 FrameMode: VideoBitrateMode: ScanType: Progressive AudioCodec: MPEG Audio AudioBitrateMode: CBRFile is: Red.avi Format: AVI VideoFormat: VP6 CodecID: VP6F Resolution: 320x240 DAR: 4:3 or 1.333 PAR: 1.000 FrameMode: VideoBitrateMode: ScanType: AudioCodec: MPEG Audio AudioBitrateMode: CBR File is: Blued.avi Format: AVI VideoFormat: MPEG-4 Visual CodecID: XVID Resolution: 512x384 DAR: 4:3 or 1.333 PAR: 1.000 FrameMode: VideoBitrateMode: ScanType: Progressive AudioCodec: MPEG Audio AudioBitrateMode: CBRFile is: Green.avi Format: AVI VideoFormat: MPEG-4 Visual CodecID: XVID Resolution: 512x384 DAR: 4:3 or 1.333 PAR: 1.000 FrameMode: VideoBitrateMode: ScanType: Progressive AudioCodec: MPEG Audio AudioBitrateMode: CBRFile is: Red.avi Format: AVI VideoFormat: VP6 CodecID: VP6F Resolution: 320x240 DAR: 4:3 or 1.333 PAR: 1.000 FrameMode: VideoBitrateMode: ScanType: AudioCodec: MPEG Audio AudioBitrateMode: CBR File is: Blued.avi Format: AVI VideoFormat: MPEG-4 Visual CodecID: XVID Resolution: 512x384 DAR: 4:3 or 1.333 PAR: 1.000 FrameMode: VideoBitrateMode: ScanType: Progressive AudioCodec: MPEG Audio AudioBitrateMode: CBRFile is: Green.avi Format: AVI VideoFormat: MPEG-4 Visual CodecID: XVID Resolution: 512x384 DAR: 4:3 or 1.333 PAR: 1.000 FrameMode: VideoBitrateMode: ScanType: Progressive AudioCodec: MPEG Audio AudioBitrateMode: CBRFile is: Red.avi Format: AVI VideoFormat: VP6 CodecID: VP6F Resolution: 320x240 DAR: 4:3 or 1.333 PAR: 1.000 FrameMode: VideoBitrateMode: ScanType: AudioCodec: MPEG Audio AudioBitrateMode: CBR
- Third problem is tht no linebreak occurs before file name
Code:@echo off goto :START :INFO mediainfo --Inform=file://template.txt "%folder%!%%1!" >>info.txt echo. >>info.txt goto :EOF :START setLocal EnableDelayedExpansion echo. >info.txt set /P "folder=Enter folder path: " set /P "_input=Search all files (y/n): " if /I "%_input%" == "y" set _str=.wmv$ .mpg$ .mkv$ .mpeg$ .mp4$ .avi$ if /I "%_input%" == "n" set /P "_str=Enter file string: " dir %folder% /B /O:N | findstr /I "%_str%" >filename.txt for /f "tokens=* delims= " %%a in (filename.txt) do CALL :INFO %%a del filename.txt cls pause
-
Sorry, I didn't fully vet your code; besides I don't have all the parameters of what you're doing. You originally said everything was working until the ELSE loop, so I just copy/pasted what you did apart from what was the obvious problem that answered your original question.
If I take a more serious look at it; look at the contents of FILENAME.TXT (so don't delete it at the end of the batch). You'll see that all the files are listed one per line and in alphabetical order, so you don't need to specify that the string to search for is at the end of a line (that's the $ in .AVI$ .MPG$...) (ok, it might be helpful if you get a filename like MOVIE.MPG.AVI, but personally I think the batch deserves to fail with such filenames).
Next, if you test _input only for a N value the batch will crash when you accidentally hit B or M. The reason IF NOT didn't work is that the NOT was in the wrong place. Even then we're still looking for Y or N, any other key will crash the batch. There are many ways to prevent that:
Code::START echo. >info.txt set /P "folder=Enter folder path: " :OOPS cls set /P "_input=Search all files (y/n): " if /I not "%_input%" == "y" if /I not "%_input%" == "n" GOTO :OOPS if /I "%_input%" == "y" set _str=.wmv .mpg .mkv .mpeg .mp4 .avi if /I not "%_input%" == "y" set /P "_str=Enter file string: "
Code::START echo. >info.txt set /P "folder=Enter folder path: " set /P "_input=Search all files (y/n): " if /I "%_input%" == "y" ( set _str=.wmv .mpg .mkv .mpeg .mp4 .avi ) ELSE ( set /P "_str=Enter file string: " )
Code::START set _str=.wmv .mpg .mkv .mpeg .mp4 .avi echo. >info.txt set /P "folder=Enter folder path: " set /P "_input=Search all files (y/n): " if /I not "%_input%" == "y" set /P "_str=Enter file string: "
You might have noticed I removed the delayedexpansion, most of the time you don't need it and it's mostly used inside a FOR loop. Also, the syntax was wrong: "%folder%!%%1!" should have been "%folder%!1!" if it was to be used. Except that %1 is always updated every time the subroutine is called. It would have made more sense to used it on %a (that is !a!), but again, the FOR command variable is always updated during the loop.
When you see a result repeating with a FOR loop, it means your command is not parsing the way you expect. In your case the problem is the use of FOR /F. That command is used to separate the content of the fileset in brackets and output multiple variables according to the TOKEN and DELIMS parameters i.e. you could end up with %a %b %c... You set the TOKEN to *, you told the FOR command to take the contents of FILENAME.TXT and place it all inside 1 variable, hence you get the mediainfo results for all files with no separation in 1 bunch, but since there are 3 filenames to process by FOR it repeats 3 times. This is what you need to use:
Code:for %%a in (filename.txt) do CALL :INFO %%a
-
so...i am desperate to understand how this all works & I gratify you for providing time to make me understand.
Let me split the bat file because till the filename.txt creation everything works fins its the naughty for loop & subroutine connection that is absurd...
This part is ok & is thus skipped
Code:@echo off goto :START :INFO mediainfo --Inform=file://template.txt "%folder%!a!" >>info.txt echo. >>info.txt goto :EOF :START setLocal EnableDelayedExpansion echo. >info.txt set /P "folder=Enter folder path: " set /P "_input=Search all files (y/n): " if /I "%_input%" == "y" set _str=.wmv$ .mpg$ .mkv$ .mpeg$ .mp4$ .avi$ if /I not "%_input%" == "y" set /P "_str=Enter file string: " dir %folder% /B /O:N | findstr /I "%_str%" >filename.txt
Code:Blued.avi Green.avi Red.avi
Code:echo. >info.txt @echo on echo. >info.txt goto :START :INFO mediainfo --Inform=file://template.txt "d:movies/%1" >>info.txt echo. >>info.txt goto :EOF :START for /f "tokens=* delims= " %%a in (filename.txt) do call :INFO %%a pause
Code:mediainfo --Inform=file://template.txt "d:movies/{name of media file with extension}" >>info.txt
The limitation I was talking about - For instance if our filename.txt contains a name with spaces in it
Code:Blued the.avi Green.avi Red.avi
Code:mediainfo --Inform=file://template.txt "d:movies/%*" >>info.txt
Code:@echo off setLocal EnableDelayedExpansion echo. >info.txt set /P "folder=Enter folder path: " set /P "_input=Search all files (y/n): " if /I "%_input%" == "y" set _str=.wmv$ .mpg$ .mkv$ .mpeg$ .mp4$ .avi$ if not /I "%_input%" == "y" set /P "_str=Enter file string: " dir %folder% /B /O:N | findstr /I "%_str%" >filename.txt for /f "tokens=* delims= " %%a in (filename.txt) do ( set in=%in%%%a mediainfo --Inform=file://template.txt "%folder%!in!" >>info.txt echo. >>info.txt ) del filename.txt cls pause
-
This is weird I posted a reply to this last morning; oh well, here we go again.
According to http://ss64.com/nt/for_f.html "tokens=* delims= " are right for this job, unlike you said?
The reason this
Code:for /f "tokens=* delims= " %%a in (filename.txt) do ( set in=%in%%%a mediainfo --Inform=file://template.txt "%folder%!in!" >>info.txt echo. >>info.txt )
One thing I find odd with the code above, set in=%in%%%a, this form is used to keep adding to a variable without losing the previous contents. I'm not sure that during a FOR loop this would happen, but at the last iteration the variable in should include all the previous values of %a. I think it should be set in=%%a.
In this
Code::INFO mediainfo --Inform=file://template.txt "d:movies/%1" >>info.txt echo. >>info.txt goto :EOF :START for /f "tokens=* delims= " %%a in (filename.txt) do call :INFO %%a
Shouldn't the mediainfo path be "d:\movies\%*"? Mind the slashes when you input the folder name. You might be better off with hard coding the slashes, as in "%folder%\!in!", then you would only type d:\movies when prompted for the folder.
There are many ways to arrive at the same results, whether you're using subroutines or nested commands, both should work.Last edited by nic2k4; 3rd Nov 2012 at 23:28.
-
Thank you very much nick,
you proved to be a devote teacher for a noob like me, now I understand fully.
On a side note I have PMed you hope you reply soon.
Similar Threads
-
[C++] How to read progress from CMD prompts like FFMPEG's
By squadjot in forum ProgrammingReplies: 5Last Post: 12th Feb 2021, 06:49 -
dos cmd that follows folder view ? [solved]
By vhelp in forum ComputerReplies: 23Last Post: 28th Oct 2012, 18:34 -
Noobs approach to automate x264 cmd
By ioncube in forum ProgrammingReplies: 2Last Post: 24th Oct 2012, 23:40 -
how to run as admin in CMD in Windows XP?
By jyeh74 in forum Newbie / General discussionsReplies: 7Last Post: 29th Jan 2010, 18:26 -
wildcards in cmd
By cL0N31 in forum ComputerReplies: 6Last Post: 3rd Apr 2009, 20:58