Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I apologize in advance as this is a simple question.

So I'm attempting to scan a Class C to identify all mail servers by IP. The vast majority of IPs aren't mail servers. I'm trying to filter out the ones that are.

I've tried the following but they haven't returned what I wanted.

nmap -p 25 | grep report && grep open 


nmap -p (grep report | grep open)

Is there a different utility that I should use? Or is it a problem with my syntax?

share|improve this question

It's not clear for me, are you need strings containing only report or open? If so, use: grep :

nmap | grep -E "report|open"

sed :

nmap | sed '/report\|open/!d'

if report and open together

grep :

nmap | grep report | grep open

sed :

nmap | sed '/report.*open\|open.*report/!d'
share|improve this answer
Understood. Thank you. – John Smith Jun 7 '12 at 12:58
With actual regex! +1 – Tim Jun 7 '12 at 13:01

Rather than post-processing with grep, try passing the --open option to Nmap. This will hide all closed or filtered ports. You can use the -oG or -oA options to output "grepable" results, too. Here's an example that does what I think you're looking for:

nmap -p 25 --open -oA smtp-servers-%y%m%d

The results would be in smtp-servers-20120607.nmap, smtp-servers-20120607.gnmap, and smtp-servers-20120607.xml. You can get IP addresses for open SMTP servers like so:

awk '/\<25/open/tcp/ {print $2}' smtp-servers-*.gnmap

If you really need this all in one pipeline, you could do it like so:

nmap -p 25 --open -oG - | awk '/\<25/open/tcp/ {print $2}'
share|improve this answer

You need a pipe to both grep invocations:

nmap ... | grep report | grep open

Or, since you tagged with awk, just informatively:

nmap ... | awk '/report/ && /open/'

And sed:

nmap ... | sed '/report/!d;/open/!d'
share|improve this answer
Your sed variant will fail. it will delete both report and open strings, obviously because open doesn't much report and vice versa. Also grep | grep and grep -e -e are not similar. First one will match only strings containing report and open, second one will much either only report either only open either both together. – rush Jun 7 '12 at 12:34
All the results of the grep statements are still kicking back IP addresses that do not have port 25 open. Ideally I'd like the statement only to display IPs with open port 25 nothing else. But your suggestions are a lot closer to my intent. Thanks! – John Smith Jun 7 '12 at 12:42
@rush you're right about grep -e -e, but for sed, as I understand, OP wants both report and open on the line, the sed will do that properly. – Kevin Jun 7 '12 at 13:01

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

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