Tuesday 8 October 2013

Windows: Concatenate output from multiple commands & output redirection

I was trying to be creative and flex my rusty Windows shell/DOS/cmd scripting using findstr, nslookup and Windows/DOS command redirection...

I was having to repeatedly run the same commands over and over with as few keystrokes as possible:

ipconfig /flushdns >null 2>1 && nslookup SERVER1 && nslookup SERVER2 && ...
  • >null
    This gets rid of normal output (STDOUT, or Standard Output) from displaying on the screen.  Normally STDOUT is connected to the current terminal (command window), so I redirect to the built-in black hole, which is file descriptor 'null', or device /dev/null in UNIX/Linux.
  • 2>1
    This gets rid of error messages from the screen (STDOUT).  When redirecting both STDOUT and STDERR from a single command they have to appear in numerical order of their codes, so it goes STDIN(0), STDOUT(1), STDERR(2).  '2>1', effectively says "redirect file descriptor 2 (STDERR) to the same place that we've sent 1 (STDOUT).
  • &&
    I only want the subsequent nslookup commands to run if the first one, flushdns is successful (if its return code is >0, zero being success in Windows/DOS), so I use '&&' (same in UNIX/Linux).
Now I wanted to concatenate the output from all the commands into a single string and then strip out matching lines... Just wrap the commands in normal parentheses (like this):

( ipconfig /flushdns >null 2>1 && nslookup SERVER1 && nslookup SERVER2 ) | findstr /b "N A"

The 'b/' tells findstr to match beginning of lines.  Putting the search terms in double quotes separated with spaces means use logical ORs so it matches any one of them.  So we end up with the output we're looking for:

( ipconfig /flushdns >null 2>1 && nslookup SERVER1 && nslookup SERVER2 && nslookup SERVER3  ) | findstr /b "Server Name Address"
Server:  gs1gpcmadcv01.gphc.local
Address:  172.16.82.1
Name:    GPHCDMZWS01.gphc.local
Address:  172.17.82.10
Server:  gs1gpcmadcv01.gphc.local
Address:  172.16.82.1
Name:    GPHCDMZDWWS01.gphc.local
Address:  172.17.82.11
Server:  gs1gpcmadcv01.gphc.local
Address:  172.16.82.1
Name:    GPHCDMZDWSTG01.gphc.local
Address:  172.17.82.13

If wish I knew how to strip out the two lines that relate to the DNS server itself - it gives the name of the Server and its Address before the target host we're resolving.  Maybe grep/awk on UNIX/Linux would be easier than figuring out how to handle line breaks with findstr, which doesn't seem to handle them at all without some dos scripting black magic!