How to Use seq With for Loop in Bash
Last updated
Last updated
To generate a pattern of numbers, we have the readily available seq command. This command in conjunction with the loop with the Bash for loop helps to perform a block of operations on each number in the sequence. In this tutorial, we learn how to use seq command with the for loop in Bash.
The built-in seq command's sole purpose is to generate a sequence of numbers. A Bash for loop can be easily integrated with seq command to iterate through the numbers generated.
Syntax:
for
iterator in
$(seq
START FACTOR END)do………done
By default, seq generates a sequence of numbers from 1 to LAST with a step size of 1.
START is the first and LAST is the last number in the sequence. FACTOR is the step size by which we increment the START value.
Let's look into how to generate sequences of numbers, iterate over them in loops, and work with variables.
We often take help of the seq command when it comes to using the for loops where we have to deal with a that are in some sequence. Let us consider this simple example:
#!/bin/bashfor
i in
$(seq
1 5)do echo
$i done
We are generating numbers from 5 to 10 in sequence using the seq command. This is then used by the for loop to iterate over each number in the sequence. The value of the iterator "i" is displayed on the terminal using the echo command.
We can notice that we did not provide the FACTOR by which the number has to increment. This is because its default value is 1. To make the loop perform the operation in the reverse fashion, we just change the order inside the seq command and provide the FACTOR as -1. We can consider this example:
#!/bin/bashfor
i in
$(seq
5 -1 1)do echo
$i done
This will print the numbers in reverse order from 5 to 1 as we have set the FACTOR to -1.
To make the loop increment by a count of two everytime we just need to set the FACTOR to 2:
#!/bin/bashfor
i in
$(seq
1 2 10)do echo
$i done
This will print all the odd numbers between 1 to 9. After printing the first value of the iterator, which is 1, the next value of the iterator gets incremented by 2. Hence, it prints 3. This goes on till 9 after which the value of the iterator becomes 11, exceeding the value 10. Hence, the loop finally terminates.
When we are developing complex scripts that require iterating over for loops using the seq command, we might find the values be available in the variables. To use those variables directly in the for loop, we need to place that variable in the syntax we saw above. Don’t forget to miss the $ prefix before the variable.
Example:
#!/bin/bash
START=0FACTOR=50END=500for
i in
$(seq
$START $FACTOR $END)do echo
$i done
The seq command generates a sequence of numbers from 0 to 500 in steps of 50. The for loop then iterates over each number in the sequence. The value of the iterator "i" is displayed using the echo command.
Let us consider this script which uses seq command with large numbers
#!/bin/bashfor
i in
$(seq
100000000 2 1000000000000)do echo
$idone
If we run this script, there won't be any errors but the loop won't start either. The problem is in the seq command. $(seq ...) is expanded into a list of words before the loop is executed. As a result our initial command expands to something like:
This result is much too long, which is what causes the infinite delay in starting the loop.
Let us suppose, we have this script,
#!/bin/bashfor
i in
$(seq
1000000000000 2 1000000000004)do echo
$idone
This script will work as expected since it will immediately boil down to:
Hence, the seq command will be able to expand the numbers for the for loop act upon.
We saw we cannot use the seq command to iterate over large numbers, say from 100000000 to 1000000000000. But, if we still want to iterate over large numbers, we can achieve that using the traditional C type for loop syntax.
#!/bin/bashfor
(( i = 100000000; i <= 1000000000000; i++ ))do echo
$idone
We will create a pinger where our script will iterate over a range of IPv4 addresses in sequence. We check the availability of the IP using the ping command. It will redirect the IP to a text file provided it's available. Otherwise, we will send it to a different file, meant for storing failed pings.
#!/bin/bash
START=30END=50IPSERIES=20.16.2for
ip in
$(seq
$START $END)do
ping
-c 1 $IPSERIES.$ip 1>/dev/null
2>&1 RC=$? if
[ $RC -eq
0 ] then echo
"Ping successful to $ip" echo
"$ip"
>> success.txt else echo
"Ping unsuccessful to $ip" echo
"$ip"
>> fail.txt fidone
1. Our script acts as a ping sweeper.
2. We have defined the START and END variable to ping a tha range of IP addresses present
3. We have defined the IPv4 series in the variable IPSERIES.
4. We have written a for loop with the seq command to generate numbers from 30 to 50 sequentially.
6. We ping this IP using the ping command. We have used the -c flag and passed 1. This means we want to ping that particular IP only once to see if the connection is successful.
7. We will store the IP addresses that respond to our ICMP requests in the file success.txt.
8. Otherwise, that IP will be sent to the fail.txt, indicating failure to ping. We use the for loop to iterate through a given IP range.
Our Bash script will verify the existence of a Linux-based user. We will extract the usernames from the /etc/passwd file. For loop in conjunction with break will verify if the user exists and terminate the loop as soon as it's found.
#!/bin/bash
cities=("Paris"
"London"
"Oslo"
"Moscow")for
i in
$(seq
0 $((${#cities[@]} - 1)))do echo
"$i : ${cities[$i]}"done
1. We have created an array of cities containing the elements: "Paris", "London". "Oslo", and "Moscow".
2. The seq command ensures we use a sequence of numbers from 0 to the last index of the array.
3. The number of elements present in this array gets computed using the #cities[@].
4. Reducing this count by 1 will give us the final element of the array. We do this using ${#fruits[@]} - 1
5. We run the loop and in every iteration, the iterator variable "i" is set to the current index in the sequence.
6. The element is determined using ${cities[$i]}.
7.We output the index along with the element.
5. For every iteration, we take the IPSERIES variable and it with the iterator variable "ip" to develop the needed IPv4 address.