Batch file: evaluating command output with regex?

batch file pattern matching
findstr output to file
batch file to find text in multiple files
search for a string in text file using batch script
findstr examples in batch files
findstr regex
batch find substring position
findstr: cannot open

I have made a Windows batch file based on some examples I have found elsewhere. What it does is it parses a folder for a specific file type (.mkv) and then runs mkvmerge.exe from the MKVToolNix folder. The command produces an output, listing the different tracks in the container.

The core of the file is

 set rootfolder="Z:\Movies"
 for /r %rootfolder% %%a in (*.mkv) do (
   for /f %%b in ('mkvmerge -i "%%a" ^| find /c /i "chapters"') do (
     if [%%b]==[0] (
       echo "%%a" has no chapters
     ) else (
       echo Doing some interesting stuff!
     )
   )
 )

The above example is just part of the file, rootfolder is set to the folder I want parsed, of course, and upon finding a file with chapters in it, it will run additional commands. It all works beautifully but I also want to check for subtitles at the same time. The find command doesn't take regular expressions or I could just have added "chapters subtitles". My efforts using other commands, like findstr, haven't really worked. How do I go about using RegEx here?

This is an example output, running mkvmerge.exe on an .mkv file

mkvmerge.exe -i "Snow White and the Seven Dwarfs (1937) [tt0029583].mkv"
File 'Snow White and the Seven Dwarfs (1937) [tt0029583].mkv': container: Matroska
Track ID 0: video (MPEG-4p10/AVC/h.264)
Track ID 1: audio (DTS)
Track ID 2: audio (AC-3)
Track ID 3: subtitles (HDMV PGS)
Track ID 4: subtitles (HDMV PGS)
Chapters: 26 entries

This example has both subtitle and chapter tracks and the batch file will find the keyword "chapters" (it's set to ignore case). I also want to catch the files that contain the keyword "subtitles" even when there are no chapters.

To clarify my intent here, I want the code to:

  • Parse through the given folder
  • For all .mkv files, do mkvmerge /i which will output (as text) the streams in that file
  • Look at that output and if it contains the word(s) "chapters" and/or "subtitles" trigger some action.

Since you appear to make no distinction between whether one string or the other (or both) is detected, then

@Echo off
set rootfolder="Z:\Movies"
for /r %rootfolder% %%a in (*.mkv) do (
 mkvmerge -i "%%a" | findstr /i "^Chapters subtitles" >nul
 if errorlevel 1 (
  echo Neither Chapters nor subs found in "%%a"
 ) else (
  echo Chapters or subs found in "%%a"
 )
)

would likely be easier.

How to set to a variable, the result of a expression, The FOR command can be used to chop up a line into tokens so you can grab just the part you want. With /f you can run it on the output of other commands, in this case the output of Also if using in a batch file you need %%i in place of %i. It’s Day Two of Batch File Week. Don’t worry, it’ll be over in a few days. There is no obvious way to read the output of a command into a batch file variable. In unix-style shells, this is done via backquoting. x=`somecommand` The Windows command processor does not have direct backquoting, but you can fake it by abusing the FOR command.

Thanks LotPings for your effort. I learned something about tokens that will be very useful. Your script also got me on the right track (learning a few more commands on the way.

Your script ended up looking like this:

:: Q:\Test\2018\05\27\SO_50555308.cmd
@Echo off
set rootfolder="Z:\Movies"
for /r %rootfolder% %%a in (*.mkv) do (
    set "found="
    for /f "tokens=1-4* delims=: " %%b in (
        'mkvmerge -i "%%a" ^| findstr /i "^Chapters subtitles"'
    ) do (
        if /i "%%b"=="Chapters" set found=1
        if /i "%%e"=="subtitles" set found=1
    )
    if defined found (
        echo Chapters or subs found in "%%a"
    ) else (
        echo.
    )
)

All I needed was to check whether one of my keywords were present in any of the tokens and then set a flag accordingly and after the loop do the appropriate action, resetting the flag for the next file.

Use findstr on Windows to find text in files and command outputs , If you want to find specific text in files, in a command line output or is not case sensitive; /R -- use search strings as regular expressions  What I want to do is grab the output of the hostname command and store in in a variable. I am thinking there must be some kind of directive in the batch file, either special characters surrounding the expression, or some kind of a switch, to say "don't treat this string as a LITERAL, instead EVALUATE it and return me the result". Help?

Still unclear how a line with Subtitles would look like. Presuming the values Chapters and Subtitles appear in 1st column The for /f splits the lines at colon and space (adjacent delims count as one) into tokens 1=%%b and 2=%%c the possible unsplitted rest in token 3=%%d The space separated (ORed) RegEx search words anchored ^ at line begin will only match chapters/subtitles.

:: Q:\Test\2018\05\27\SO_50555308.cmd
@Echo off
set rootfolder="Z:\Movies"
for /r %rootfolder% %%a in (*.mkv) do (
    for /f "tokens=1-4* delims=: " %%b in (
        'mkvmerge -i "%%a" ^| findstr /i "^Chapters subtitles"'
    ) do (
        if /i "%%b"=="Chapters" if "%%c"=="0" (
            echo "%%a" has no chapters
        ) else (
            echo "%%a" has %%c chapters
            echo Doing some interesting stuff!
        )
        if /i "%%e"=="subtitles" echo "%%a" %%b %%b %%d: %%e %%f
    )
)

Findstr - Search for strings - Windows CMD, /R Evaluate as a regular expression. /G:StringsFile Get search string from a file (/ stands for console). The format of matching line output from FINDSTR is:. Similar to the Left function in VB a batch script can return a specified number of characters from the left side of a string by specifying a substring for an expansion given a position of 0 and a length using :~ while expanding a variable content. The example shows how to return the first 4 characters of a string.

Batch files, Regular Expressions ▻ Command line validation, and parameter files as an alternative, are discussed in their own dedicated page. However, when you enter the command ECHO %Input% the output will look like this: ECHO %Input​% is evaluated to ECHO abc&ping ::1 which is in turn interpreted as: Findstr is a powerful command that you may use to search for strings in files or to filter command line output. You may use it to scan entire directory structures or drives for files that match the selected string or part of it, and to find specified text in command line outputs quickly.

sed, a stream editor, See also the W and s///w commands for writing output to other files. sed may be invoked with the following command-line options: Note that modifiers to regular expressions are evaluated when the regular expression is compiled, thus it is  > You write a batch file and run it at the command prompt -- or in the > batch debugger, which is easier & more powerful than trying to run a > complex command at the command prompt.

Sublime Text Build Tool Tutorial, Step 5: Output Syntax This tutorial is geared towards windows and building with a batch file, however much of the We will be making a build system that uses the Microsoft Visual Studios Command Line Visual C Compiler, so if you want The actual regular expression that gets evaluated looks something more like this:. Many batch file renaming programs for Windows and OS X have support for regexps, as well as the cross-platform searching tool GREP (which we touched on in our Bash Scripting for Beginners Guide) and the Awk command-line tool for *Nix. In addition, many alternative file managers, launchers, and searching tools use them, and they have a very important place in programming languages like Perl and Ruby.

Comments
  • You should provide a sample output you want to parse. Not everyone uses mkvmerge.
  • Thanks, I will add an example output, although I didn't find it necessary at the time of writing. The point here was to scan for either of 2 keywords instead of just one.
  • You should also share your (failed) findstr attempts...
  • Good point aschipfl, but since I wasn't aware of the mechanics of the for /f loop or the format of the output, they never amounted to anything but empty variables or incorrect syntax.
  • Spot on! That was exactly what I was trying to achieve. Took me a while until I spotted the missing ( in the if statement.
  • @KarstenJensen If this answer solved your issue, please select it as the correct answer by selecting the grey tick mark on the left of the answer.
  • Thanks, although I'm not really sure it does what I need it to do and it doesn't seem to catch subtitles at all. I want it to look at the output of each movie file and then If the output contains the word "subtitles" and/or "chapters", then do stuff, otherwise skip.
  • To parse it properly I need a sample from subtitle you didn't provide
  • The example above contains Video track, 2 audio tracks, 2 subtitle tracks and chapters
  • Didn't recognize that, my anchor at line begin can't match, how do you want the output to be?
  • I don't really need an output. I just need a check whether a given file, based on the output from the mkvmerge command, contains either subtitle tracks and/or chapters. The problem is I'm not familiar with pipes or the for loops. If it was an IF statement I would just put OR.