I have the following command to process nmap output that contains a list of ips that I've been asked to scan:

cat ping-sweep.txt | grep "report for" | cut -d " " -f5

This is providing me a list of only the ip's (one per line) which I'd then like to scan for web servers.

I can scan an individual host with the following:

nmap -v -p 80,443,8080

I'd like to perform this scan on every ip in my list however piping it into nmap doesn't appear to work. Do I need to create a bash script with a foreach to do this or is there something simple that I'm missing?


The first step would be trying to use Nmap in the way it was designed. Since Nmap performs host discovery ("ping sweep") prior to each port scan, you can do both steps at once with this simple command:

nmap -p 80,443,8080 [TARGETS]

If you really do need to perform the host discovery separately from the port scan, then use Nmap's robust machine-readable output options like XML or Grepable output. For older versions of Nmap, the easiest way would be to do the host discovery and save the Grepable output like so:

nmap -sn [TARGETS] -oG ping-sweep.gnmap

Then you can extract the IP addresses easily with awk:

awk '/Status: Up/{print $2}' ping-sweep.gnmap > targets.txt

and import them directly to Nmap:

nmap -p 80,443,8080 -iL targets.txt

Alternatively, with Nmap 7.00 or newer, you can use the XML output format saved with -oX ping-sweep.xml and the targets-xml NSE script:

nmap -p 80,443,8080 --script targets-xml --script-args newtargets,iX=ping-sweep.xml

With any of these options, if your host discovery scan is recent enough, you can add the -Pn option to skip the host discovery phase of the port scan. This saves you a tiny bit of scan speed, since you ought to be able to count on those same hosts still being up.

What you really should not do is any solution involving loops or xargs, since these will end up launching a separate Nmap instance for each target. This is wasteful and unnecessary, since each instance will have to duplicate the work of loading data files and sending timing probes to monitor network capacity, and the separate instances will be competing with each other for network resources instead of cooperating. Also, you'll have to recombine their separate outputs in the end.

| improve this answer | |

You can give nmap all the addresses to scan as parameters, like this:

nmap -v -p 80,443,8080 $(grep "report for" ping-sweep.txt | cut -d" " -f5)

This runs grep on your file (no need for cat), then filters grep's output through cut, and the result of that is used to build the nmap command line. This is known as command substitution.

There are loops in the shell, and you could use one, in various ways:

grep "report for" ping-sweep.txt | cut -d" " -f5 | while read ip; do
    nmap -v -p 80,443,8080 "${ip}"


for ip in $(grep "report for" ping-sweep.txt | cut -d" " -f5); do
    nmap -v -p 80,443,8080 "${ip}"

Both of these will run nmap with one address at a time.

| improve this answer | |

Most generically, you can use xargs to pass each line as command-line argument to a command, like this:

cat ping-sweep.txt | grep "report for" | cut -d " " -f5 | xargs -I'{}' nmap -v -p 80,443,8080 '{}'
| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.