Read range of numbers into a for loop
NickName:tobi78 Ask DateTime:2016-07-12T01:48:20

Read range of numbers into a for loop

So, I am building a bash script which iterates through folders named by numbers from 1 to 9. The script depends on getting the folder names by user input. My intention is to use a for loop using read input to get a folder name or a range of folder names and then do some stuff.

Example:
Let's assume I want to make a backup with rsync -a of a certain range of folders. Usually I would do:

for p in {1..7}; do
     rsync -a $p/* backup.$p
done

The above would recursively backup all content in the directories 1 2 3 4 5 6 and 7 and put them into folders named as 'backup.{index-number}'. It wouldn't catch folders/files with a leading . but that is not important right now.

Now I have a similar loop in an interactive bash script. I am using select and case statements for this task. One of the options in case is this loop and it shall somehow get a range of numbers from user input. This now becomes a problem.

Problem:
If I use read to get the range then it fails when using {1..7} as input. The input is taken literally and the output is just:

{1..7}

I really would like to know why this happens. Let me use a more descriptive example with a simple echo command.

var={1..7} # fails and just outputs {1..7}
for p in $var; do echo $p;done

read var # Same result as above. Just outputs {1..7}
for p in $var; do echo $p;done

for p in {1..7}; do echo $p;done # works fine and outputs the numbers 1-7 seperated with a newline.

I've found a workaround by storing the numbers in an array. The user can then input folder names seperated by a space character like this: 1 2 3 4 5 6 7

read -a var # In this case the output is similar to the 3rd loop above
for p in ${var[@]}; do echo $p; done

This could be a way to go but when backing up 40 folders ranging from 1-40 then adding all the numbers one-by-one completely makes my script redundant. One could find a solution to one of the millennium problems in the same time.

Is there any way to read a range of numbers like {1..9} or could there be another way to get input from terminal into the script so I can iterate through the range within a for-loop?

This sounds like a question for google but I am obviously using the wrong patterns to get a useful answer. Most of similar looking issues on SO refer to brace and parameter expansion issues but this is not exactly the problem I have. However, to me it feels like the answer to this problem is going in a similar direction. I fail to understand why when a for-loop for assigning {1..7} to a variable works but doing the same like var={1..7} doesn't. Plz help -.-

EDIT: My bash version:

$ echo $BASH_VERSION
4.2.25(1)-release

EDIT2: The versatility of a brace expansion is very important to me. A possible solution should include the ability to define as many ranges as possible. Like I would like to be able to choose between backing up just 1 folder or a fixed range between f.ex 4-22 and even multiple options like folders 1,2,5,6-7

Copyright Notice:Content Author:「tobi78」,Reproduced under the CC 4.0 BY-SA copyright license with a link to the original source and this disclaimer.
Link to original article:https://stackoverflow.com/questions/38313141/read-range-of-numbers-into-a-for-loop

Answers
chepner 2016-07-11T17:53:50

Brace expansion is not performed on the right-hand side of a variable, or on parameter expansion. Use a C-style for loop, with the user inputing the upper end of the range if necessary.\n\nread upper\nfor ((i=1; i<=$upper; i++)); do\n\n\nTo input both a lower and upper bound separated by whitespace\n\nread lower upper\nfor (i=$lower; i <= $upper; i++)); do\n\n\n\n\nFor an arbitrary set of values, just push the burden to the user to generate the appropriate list; don't try to implement your own parser to process something like 1,2,20-22:\n\nwhile read p; do\n rsync -a $p/* backup.$p\ndone\n\n\nThe input is one value per line, such as\n\n1\n2\n20\n21\n22\n\n\nEven if the user is using the shell, they can call your script with something like\n\nprintf '%s\\n' 1 2 20..22 | backup.sh\n\n\nIt's easier for the user to generate the list than it is for you to safely parse a string describing the list.",


More about “Read range of numbers into a for loop” related questions

Read range of numbers into a for loop

So, I am building a bash script which iterates through folders named by numbers from 1 to 9. The script depends on getting the folder names by user input. My intention is to use a for loop using read

Show Detail

shell - iterating a loop for a (validated) supplied number or range of numbers

I need to accept input from user (i.e. 'read'). This input can be either a single positive number or a range of numbers (in the form X-Y ). I then need to validate this input and perform an itera...

Show Detail

Java, sum range of numbers in a for loop

Sorry I have been trying to figure this out and it's driving me crazy. I need to write a java program that sums a range of numbers entered by the user and by the count of numbers entered by a user...

Show Detail

Adding Numbers in a Range with for() Loop

I'm having trouble filling out a question on an online python tutorial. It seems really simple but for the life of me I can't figure it out. This is the problem "write a for loop that adds all the

Show Detail

batch loop in a range of numbers

I want to do something in batch for loop in a range of numbers. FOR /L %%parameter IN (start,step,end) DO command This command is probably the one I need, but the "end" value is stored in a vari...

Show Detail

loop through a collection of range of numbers in one line powershell

I am trying to find a way to loop through a collection of range of numbers in PowerShell. I have tried below and it works foreach ($i in 1..3) { &quot;$i&quot; } foreach ($i in 1,2,3) { &q...

Show Detail

Create variable within a range of numbers except a list of numbers

I have the following variable with a list of numbers vlist=&quot;1 13 20 21 22 24 25 28 240 131 133 136 138 224&quot; In the next loop I want to input a number between 1 - 250 except the numbers in

Show Detail

Assigning range of numbers to a letter in python

Is it possible to assign range of numbers to a letter in python, without getting into the loop, I am trying to print a row of numbers separated by pipe,these rows will be the index of a list conten...

Show Detail

How to efficiently find Bitwise OR of a range of numbers

Given a range of number [a,b], how to efficiently find Bitwise OR of all numbers in this range. Running a loop for range [a,b] and computing Bitwise OR of all the numbers individually is too much t...

Show Detail

python range and for loop understanding

I am new to python / coding and looking to understanding the range function more and how it is used in conjunction with the &quot;for&quot; loop. So I know that the range function takes in 3 parame...

Show Detail