Search code examples
bashfor-loopnmap

How can I get a for loop to output once rather than every iteration?


I've made this simple bash script to run a ping scan and grab MAC addresses active on my network, output to a file, and then compare that file against a file with a list of known MAC addresses I grabbed from my ARP table in my router.

Rather than echo a result for each line that it iterates, how can I make the for loop spit out one output like "All Devices are familiar on your network"?

current code:

sudo nmap -sn 192.168.0.0/24 | grep "MAC" | awk '{print $3}'| sort > $HOME/Desktop/arp.txt

readarray -t mac <$HOME/Desktop/arptable.txt

for address in "${mac[@]}"; do
    if grep -Fxq "$address" $HOME/Desktop/arptable.txt;
    then 
        echo "$address is a known network device"
    else
        echo "WARNING: $address is an unknown device on the network"
    fi
done 

and my current output looks like:

XXXXXXXXXXXXXXXXX is a known network device
XXXXXXXXXXXXXXXXX is a known network device
XXXXXXXXXXXXXXXXX is a known network device
XXXXXXXXXXXXXXXXX is a known network device
XXXXXXXXXXXXXXXXX is a known network device
XXXXXXXXXXXXXXXXX is a known network device
XXXXXXXXXXXXXXXXX is a known network device
XXXXXXXXXXXXXXXXX is a known network device
XXXXXXXXXXXXXXXXX is a known network device
XXXXXXXXXXXXXXXXX is a known network device
XXXXXXXXXXXXXXXXX is a known network device
XXXXXXXXXXXXXXXXX is a known network device
XXXXXXXXXXXXXXXXX is a known network device
XXXXXXXXXXXXXXXXX is a known network device
XXXXXXXXXXXXXXXXX is a known network device
XXXXXXXXXXXXXXXXX is a known network device
XXXXXXXXXXXXXXXXX is a known network device
XXXXXXXXXXXXXXXXX is a known network device

Disclamer: This is just a project and not used as a serious security tool.


Solution

  • Assuming you still want to print out the WARNING messages ... keep track of the number of successes and if equal to the number of entries in the array mac[] then print your desired message, eg:

    found=0
    
    for address in "${mac[@]}"; do
        if grep -Fxq "$address" $HOME/Desktop/arptable.txt;
        then 
            ((found++))
        else
            echo "WARNING: $address is an unknown device on the network"
        fi
    done 
    
    [[ "${found}" -eq "${#max[@]}" ]] && echo "All Devices are familiar on your network"
    

    Alternatively, clear a flag if you generate any WARNING messages:

    foundall=true
    
    for address in "${mac[@]}"; do
        if ! grep -Fxq "$address" $HOME/Desktop/arptable.txt;
        then 
            echo "WARNING: $address is an unknown device on the network"
            foundall=false
        fi
    done 
    
    [[ "${foundall}" == 'true' ]] && echo "All Devices are familiar on your network"