0

So I've created this ping sweep in a bash terminal, but I want to make a neat looking script file for this:

for IPs in 192.168.0.{1..254}; do ping -c1 -W1 $IPs; done | grep -B1 "1 received" | grep "192.168.0" | cut -d " " -f2 > BashPingSweep.txt

I think I have the for loop correct, but I cant pipe the for loop into the other greps and cut then output. This is what I have now:

#!/bin/bash
for IPs in 192.168.0.{1..254}
do
    ping -c1 -W1 $IPs
done

grep -B1 "1 received"
grep "192.168.0"
cut -d " " -f2
> BashPingSweep.txt
6
  • 1
    why do you think you can't ? what's stopping you from trying to use the same block you used on a terminal in shell script? Commented Nov 25, 2017 at 9:26
  • Good point. I could just use the line and it would work. But this question is directed more toward how to pipe in this block format, if possible, rather than in a long ugly looking line of code. Commented Nov 25, 2017 at 9:48
  • Formatting lengthy statements into multiple lines is a great thing to improve maintainability, especially when dealing with shell script. Commented Nov 25, 2017 at 10:01
  • You still need the pipes; newlines and semi-colons are somewhat interchangeable, not newlines and pipes. Commented Nov 25, 2017 at 15:10
  • 1
    You can also shorten the pipeline by replace the grep/cut pair with a single awk command: grep -B1 "1 received" | awk '/192.168.0/ {print $2}' > BashPingSweep.txt. (You could incorporate the other grep into the same awk command, but that would take more work than would easily fit in a comment.) Commented Nov 25, 2017 at 15:17

2 Answers 2

4

You could try this:

#!/bin/bash

for IP in 192.168.0.{1..254}
do
    ping -c1 -W1 $IP
done |
grep -B1 "1 received" |
grep "192.168.0" |
cut -d " " -f2 \
> BashPingSweep.txt

It looks a bit awkward but it's a common way to format a lengthy pipe over multiple lines. You could also put it like this:

for IP in 192.168.0.{1..254}
do
    ping -c1 -W1 $IP
done \
| grep -B1 "1 received" \
| grep "192.168.0" \
| cut -d " " -f2 \
> BashPingSweep.txt

which is what I prefer because it's easier to see where the pipe goes.

Sign up to request clarification or add additional context in comments.

1 Comment

I prefer to put the pipes at the end of lines, but then indent all but the first command to show that they're chained off of it. But any of the above work, it's a matter of taste.
-2

You need to pipe it inside the for loop

for IPs in 192.168.0.{1..254};
do
   ping -c1 -W1 $IPs | grep -B1 "1 .* received" | grep "192.168.0" | cut -d " " -f2 > BashPingSweep.txt
done

4 Comments

This would overwrite BashPingSweep.txt on each iteration.
That provides an empty text file instead of the IP addresses it should return. Additionally, isn't the semi colon after the for unnecessary and it looks like you added a typo to the first grep. I believe your solution is grepping each value instead of the entire for loop like I had done in the example, and like yacc said, each iteration is overwriting the txt file. Thanks for the attempt though :p
This is incorrect; there is no need to move the pipe inside the loop, and in fact (besides being incorrect here) it makes the script a lot less efficient.
I thought you would update your solution to fix the behavior pointed out by OP's remark? @NezzyGuda

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.