Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Iterating over variable name in bash script

Tags:

bash

I needed to run a script over a bunch of files, which paths were assigned to train1, train2, ... , train20, and I thought 'why not make it automatic with a bash script?'.

So I did something like:

train1=path/to/first/file
train2=path/to/second/file
...
train20=path/to/third/file

for i in {1..20}
do
    python something.py train$i
done

which didn't work because train$i echoes train1's name, but not its value.

So I tried unsuccessfully things like $(train$i) or ${train$i} or ${!train$i}. Does anyone know how to catch the correct value of these variables?

like image 287
rafa Avatar asked Jun 26 '13 11:06

rafa


People also ask

How do you iterate through a variable in bash?

Example-2: Iterating a string variable using for loopCreate a bash file named 'for_list2.sh' and add the following script. Assign a text into the variable, StringVal and read the value of this variable using for loop.

What does [- Z $1 mean in bash?

$1 means an input argument and -z means non-defined or empty. You're testing whether an input argument to the script was defined when running the script.

How do you increment a variable in bash?

Increment Bash Variable with += Operator Another common operator which can be used to increment a bash variable is the += operator. This operator is a short form for the sum operator. The first operand and the result variable name are the same and assigned with a single statement.

What is $() in bash script?

$() Command Substitution According to the official GNU Bash Reference manual: “Command substitution allows the output of a command to replace the command itself.


2 Answers

Use an array.

Bash does have variable indirection, so you can say

for varname in train{1..20}
do
    python something.py "${!varname}"
done

The ! introduces the indirection, so "get the value of the variable named by the value of varname"

But use an array. You can make the definition very readable:

trains=(
    path/to/first/file
    path/to/second/file
    ...
    path/to/third/file
)

Note that this array's first index is at position zero, so:

for ((i=0; i<${#trains[@]}; i++)); do
    echo "train $i is ${trains[$i]}"
done

or

for idx in "${!trains[@]}"; do
    echo "train $idx is ${trains[$idx]}"
done
like image 168
glenn jackman Avatar answered Sep 29 '22 07:09

glenn jackman


You can use array:

train[1]=path/to/first/file
train[2]=path/to/second/file
...
train[20]=path/to/third/file

for i in {1..20}
do
    python something.py ${train[$i]}
done

Or eval, but it awfull way:

train1=path/to/first/file
train2=path/to/second/file
...
train20=path/to/third/file

for i in {1..20}
do
    eval "python something.py $train$i"
done
like image 30
Nikolai Popov Avatar answered Sep 29 '22 08:09

Nikolai Popov