2204

I want to write a script that loops through 15 strings (array possibly?) Is that possible?

Something like:

for databaseName in listOfNames
then
  # Do something
end
codeforester
  • 39,467
  • 16
  • 112
  • 140
Mo.
  • 40,243
  • 37
  • 86
  • 131

21 Answers21

3341

You can use it like this:

## declare an array variable
declare -a arr=("element1" "element2" "element3")

## now loop through the above array
for i in "${arr[@]}"
do
   echo "$i"
   # or do whatever with individual element of the array
done

# You can access them using echo "${arr[0]}", "${arr[1]}" also

Also works for multi-line array declaration

declare -a arr=("element1" 
                "element2" "element3"
                "element4"
                )
Nam G VU
  • 33,193
  • 69
  • 233
  • 372
anubhava
  • 761,203
  • 64
  • 569
  • 643
  • 157
    Note that **the double quotes around `"${arr[@]}"` are really important.** Without them, the for loop will break up the array by substrings separated by any spaces within the strings instead of by whole string elements within the array. ie: if you had `declare -a arr=("element 1" "element 2" "element 3")`, then `for i in ${arr[@]}` would mistakenly iterate 6 times since each string becomes 2 substrings separated by the space in the string, whereas `for i in "${arr[@]}"` would iterate 3 times, correctly, as desired, maintaining each string as a single unit despite having a space in it. – Gabriel Staples Jun 14 '20 at 20:13
1085

That is possible, of course.

for databaseName in a b c d e f; do
  # do something like: echo $databaseName
done 

See Bash Loops for, while and until for details.

Ohad Schneider
  • 36,600
  • 15
  • 168
  • 198
4ndrew
  • 15,354
  • 2
  • 27
  • 29
  • 27
    What is the problem with this approach? In simple cases it seems to work and, then, is more intuitive than @anubhava's answer. – Dr. Jan-Philip Gehrcke Aug 30 '12 at 11:54
  • 21
    This works particularly well with command substitution, eg `for year in $(seq 2000 2013)`. – Brad Koch May 20 '13 at 14:53
  • 26
    The 'declare' approach works best if you have to iterate over the same array in more than one place. This approach is cleaner but less flexible. – StampyCode Jan 03 '14 at 10:21
  • 21
    Why isn't this #1? It's cleaner, and you can easily reuse the array just by setting a string, i.e., `DATABASES="a b c d e f"`. – Nerdmaster Jul 02 '14 at 21:42
  • 17
    @Nerdmaster: Yes, this is a more simple (and portable) code but storage of the list of strings separated by spaces in a variable (a single string in fact) prevents the individual strings to contain spaces. The [reply of user2533809](http://stackoverflow.com/a/21178462/320437) solves this problem. ------ But there is another problem. If the list is very long and has to be updated such update operations require to copy the complete list every time so they will be very slow. – pabouk - Ukraine stay strong Nov 24 '14 at 13:30
  • @StampyCode: "If" - Sparta – user3481644 Feb 22 '23 at 11:24
354

None of those answers include a counter...

#!/bin/bash
## declare an array variable
declare -a array=("one" "two" "three")

# get length of an array
arraylength=${#array[@]}

# use for loop to read all values and indexes
for (( i=0; i<${arraylength}; i++ ));
do
  echo "index: $i, value: ${array[$i]}"
done

Output:

index: 0, value: one
index: 1, value: two
index: 2, value: three
catchdave
  • 9,053
  • 2
  • 27
  • 16
caktux
  • 5,235
  • 2
  • 19
  • 10
  • 1
    That's just for the sake of the example's output with a counter. It's also quite trivial to change that, and works just the same. – caktux Jul 09 '15 at 05:35
  • 7
    The echo at the end is buggy. You don't need to quote constants, you need to quote expansions, or can safely just quote both as follows: `echo "$i / ${arraylength} : ${array[$i-1]}"` -- otherwise, if your `$i` contains a glob it'll be expanded, if it contains a tab it'll be changed to a space, etc. – Charles Duffy Jul 09 '16 at 15:02
  • 1
    @CharlesDuffy `$i` won't contain a glob, because it's the loop counter in this example and so you control its value. – bzeaman Sep 02 '16 at 07:01
  • 11
    @bzeaman, sure -- but if you're sloppy about such things then it requires contextual analysis (as you just did) to prove something correct, and re-analysis if that context changes or the code is reused in a different place or for whatever other reason an unexpected control flow is possible. Write it the robust way and it's correct regardless of context. – Charles Duffy Sep 02 '16 at 14:57
  • 11
    This won't work for a sparse array, i.e. if the array is missing elements. For example, if you have array elements A[1]='xx', A[4]='yy' and A[9]='zz', the length will be 3 and the loop won't process all the elements. – Mr Ed Dec 12 '17 at 09:18
  • is there any reason to start the loop counter at `1` and not at `0` ? – 463035818_is_not_an_ai Sep 10 '20 at 08:57
  • @largest_prime_is_463035818: Modified answer to take into account your feedback – catchdave May 22 '21 at 01:27
  • 1
    No need to get the length of array. Simply use `for i in "${!array[@]}";` – mgutt Nov 28 '21 at 15:05
282

Yes

for Item in Item1 Item2 Item3 Item4 ;
  do
    echo $Item
  done

Output:

Item1
Item2
Item3
Item4

To preserve spaces; single or double quote list entries and double quote list expansions.

for Item in 'Item 1' 'Item 2' 'Item 3' 'Item 4' ;
  do
    echo "$Item"
  done

Output:

Item 1
Item 2
Item 3
Item 4

To make list over multiple lines

for Item in Item1 \
            Item2 \
            Item3 \
            Item4
  do
    echo $Item
  done

Output:

Item1
Item2
Item3
Item4

Simple list variable
List=( Item1 Item2 Item3 )

or

List=(
      Item1 
      Item2 
      Item3
     )

Display the list variable:

echo ${List[*]}

Output:

Item1 Item2 Item3

Loop through the list:

for Item in ${List[*]} 
  do
    echo $Item 
  done

Output:

Item1
Item2
Item3

Create a function to go through a list:

Loop(){
  for item in ${*} ; 
    do 
      echo ${item} 
    done
}
Loop ${List[*]}

Using the declare keyword (command) to create the list, which is technically called an array:

declare -a List=(
                 "element 1" 
                 "element 2" 
                 "element 3"
                )
for entry in "${List[@]}"
   do
     echo "$entry"
   done

Output:

element 1
element 2
element 3

Creating an associative array. A dictionary:

declare -A continent

continent[Vietnam]=Asia
continent[France]=Europe
continent[Argentina]=America

for item in "${!continent[@]}"; 
  do
    printf "$item is in ${continent[$item]} \n"
  done

Output:

 Argentina is in America
 Vietnam is in Asia
 France is in Europe

CSV variables or files in to a list.
Changing the internal field separator from a space, to what ever you want.
In the example below it is changed to a comma

List="Item 1,Item 2,Item 3"
Backup_of_internal_field_separator=$IFS
IFS=,
for item in $List; 
  do
    echo $item
  done
IFS=$Backup_of_internal_field_separator

Output:

Item 1
Item 2
Item 3

If need to number them:

` 

this is called a back tick. Put the command inside back ticks.

`command` 

It is next to the number one on your keyboard and or above the tab key, on a standard American English language keyboard.

List=()
Start_count=0
Step_count=0.1
Stop_count=1
for Item in `seq $Start_count $Step_count $Stop_count`
    do 
       List+=(Item_$Item)
    done
for Item in ${List[*]}
    do 
        echo $Item
    done

Output is:

Item_0.0
Item_0.1
Item_0.2
Item_0.3
Item_0.4
Item_0.5
Item_0.6
Item_0.7
Item_0.8
Item_0.9
Item_1.0

Becoming more familiar with bashes behavior:

Create a list in a file

cat <<EOF> List_entries.txt
Item1
Item 2 
'Item 3'
"Item 4"
Item 7 : *
"Item 6 : * "
"Item 6 : *"
Item 8 : $PWD
'Item 8 : $PWD'
"Item 9 : $PWD"
EOF

Read the list file in to a list and display

List=$(cat List_entries.txt)
echo $List
echo '$List'
echo "$List"
echo ${List[*]}
echo '${List[*]}'
echo "${List[*]}"
echo ${List[@]}
echo '${List[@]}'
echo "${List[@]}"

BASH commandline reference manual: Special meaning of certain characters or words to the shell.

Community
  • 1
  • 1
abc
  • 3,223
  • 1
  • 15
  • 15
  • 11
    **THIS IS WRONG.** Needs to be `"${List[@]}"` to be correct, **with the quotes**. `${List[@]}` is wrong. `${List[*]}` is wrong. Try `List=( "* first item *" "* second item *" )` -- you'll get correct behavior for `for item in "${List[@]}"; do echo "$item"; done`, but not from any other variant. – Charles Duffy May 04 '18 at 19:36
  • 1
    Yes special chars do get interpreted , which may or may not be desirable . I updated the answer to include . – abc May 27 '18 at 10:57
  • 2
    I still would strongly suggest showing the more correct/robust approach *first*. Folks often take the first answer that looks like it'll work; if that answer has hidden caveats, they may only expose themselves later. (It's not just wildcards that are broken by lack of quoting; `List=( "first item" "second item" )` will be broken into `first`, `item`, `second`, `item` as well). – Charles Duffy May 27 '18 at 15:13
  • 1
    You might also consider avoiding use of an example that might lead people to parse `ls` output, [in contravention of best practices](http://mywiki.wooledge.org/ParsingLs). – Charles Duffy May 27 '18 at 15:16
  • That maybe desirable . echo ${fileTypes[@]} ; fileTypes=(html css js PHP) ; for entry in "${fileTypes[@]}" ; do echo "$entry" ; done . It could be used piped in to other programs and it will be single words , that is how it was designed to work originally . That has to be known , learned . – abc May 27 '18 at 23:17
  • fileTypes=(html css js PHP) ; echo ${fileTypes[@]} ; for entry in ${fileTypes[@]} ; do echo $entry ; done . It could be used piped in to other programs and it will be single words , that is how it was designed to work originally . That has to be known , learned . See that in new python syntax for passing commands and switches , then have the quoted text passed as a big string , but every thing else is cut up to be passed to the subshell as commands and switches . So do not quote every thing , only quote what needs to be quoted . – abc May 27 '18 at 23:36
  • When you use `${fileTypes[@]}` unquoted, its behavior is *exactly identical* to `${fileTypes[*]}`, similarly unquoted. "Only quote what needs to be quoted" is not considered good practice -- almost half the caveats given in [BashPitfalls](http://mywiki.wooledge.org/BashPitfalls) relate to relying on string-splitting / unquoted expansion. In the places where unquoted expansion was historically used deliberately, quoted expansion of an array is an alternative thereto. – Charles Duffy May 28 '18 at 10:27
  • "" caveats given in BashPitfalls "" . That is only because nobody was shown how it works in the first place . A word is a list of letters . If want to nest lists inside lists , need to construct them appropriately and deconstruct them appropriately depending on the task/s at hand . I updated the answer any way for your objection . a=(sudo apt purge snapd) ; echo ${a[@]} ; ${a[@]} – abc May 29 '18 at 09:05
  • Eh? `${a[@]}` **is wrong**. If `a=( rsync --exclude='* *' host:/source '/path/to/dest with spaces/' )`, then only `"${a[@]}"` will do the right thing, and moreover, `echo` won't correctly represent the command that the OP's code will run (compare to `printf '%q ' "${a[@]}"; echo`, which will). And writing code that's only accurate if assumptions about your data are correct is making unnecessary bugs. – Charles Duffy May 29 '18 at 15:43
  • I'm not talking about character sets at all -- they're completely irrelevant. The point is robust handling of **all possible data**. All possible data, in this context, means all possible C strings. If you have bugs in the face of possible data, well, that means your program has bugs. An argument that people "shouldn't" ever do things that trigger your bugs, or that people who trigger those bugs are bad people, is worthless -- it doesn't stop failures from happening whether by chance or intent -- when you could write your code correctly and not have bugs at all. – Charles Duffy May 31 '18 at 20:11
  • The worst data loss event I've been present for happened when a buffer overflow in a C library used by a Python module dumped a string containing a whitespace-surrounded asterisk into a buffer used as part of a filename that was supposed to only have hexadecimal characters in it. Because it was supposed to be impossible for any files to have a non-hex name, the shell scripts responsible for cleaning up data didn't bother to quote. Because they didn't bother to quote, when they tried to delete this file, those scripts instead deleted everything in the directory. Which was full of billing info. – Charles Duffy May 31 '18 at 20:17
  • If instead of **assuming** that their assumption -- that names could only ever contain hex characters -- was true, the people building that script had added two extra characters -- a quote before the string and another after it -- weeks of data recovery work would have been avoided. – Charles Duffy May 31 '18 at 20:18
  • Linux has naming standards and naming conventions , you can not just go doing this in C or any other language . They all have rules or otherwise they do not work . Bash uses a name separator , identical to genetic code , a stop codon , which is space , the space is a char , is just does not get printed . Even a space is a character , a char . You have to know where one thing starts and where another begins and that is what a space does , what it is . The enter button is also a char , it too does not get printed. – abc May 31 '18 at 20:25
  • The worst thing i have seen was a rocket blow up from a buffer over flow of charters sets . Exceeding the machines ability , the computer chips ability . That is what i am saying , people will never understand how to program with out knowing the machine , programs have limits and they have efficiencies . As does trying not to get RSI injurys . – abc May 31 '18 at 20:31
  • Yes , have to quote control chars so they do not get interrupted , people should learn that immediately . In you example , you have to quote the has symbol , as such '*' , which means literally . Do not interprate control chars . The space char is taken by bash , it uses it for control . As the control of where one word starts and another ends . String separator . – abc May 31 '18 at 20:48
  • You're assuming that people know ahead-of-time what their data will be, and that these assumptions never turn out to be wrong. I already gave an example of a case where someone "knew" that all their filenames would match `^[0-9a-f]{24}$`... until one day when they didn't. Similarly, my current employer had a security bug when someone assumed a search string entered in an admin interface (and then passed to a shell script) would never be used for a shell injection attack. The only thing you **know** is true of a bash variable is that it's a C string -- everything else is conjecture. – Charles Duffy May 31 '18 at 20:53
  • That programmer should not of assumed it was quoted and cleaned it . The programmer did not clean it because did not know how , did not know that certain chars are needed . As of python 3 the module has being changed and warning put up to never ever ever do what you just said . The whole module has being gutted out and trashed , replaced and are now forced to use lists correctly . – abc May 31 '18 at 20:54
  • If you "clean" an identifier used as a key lookup, it no longer refers to the original target of that lookup anymore. That is, if you run `for file in *; do`, but then change the `file` variable to eliminate characters you don't expect, it then contains a different name than the one that actually exists, so if you try to read/rename/etc. the file, you're suddenly referring to a different file that doesn't actually exist. Far from being a remediation step, "cleaning" data when it's already in a system can make problems worse. – Charles Duffy May 31 '18 at 21:02
  • ...yes, one should do validation **at input time**, but if you want to be robust, you can't stop at input time -- you need to handle invalid data once it's already present (as such input-time validation *will* eventually fail), and "handling" can't always be as simple as just throwing it away. – Charles Duffy May 31 '18 at 21:03
  • Here is the bash menu entry on the double quotes : https://www.gnu.org/software/bash/manual/html_node/Double-Quotes.html – abc May 31 '18 at 21:59
  • Single quotes https://www.gnu.org/software/bash/manual/html_node/Single-Quotes.html#Single-Quotes – abc May 31 '18 at 21:59
  • string="This is a large string . The present working directory $PWD contains the files * . This is the symbol that gets a list of all files in $PWD '*' . As for not interprating '$PWD' , it does it if like it or not . " ; echo '$string' ; echo $string ; echo "$string" – abc May 31 '18 at 22:29
  • 2
    You're refuting claims I never made. I'm quite familiar with bash's quoting semantics -- see https://stackoverflow.com/tags/bash/topusers – Charles Duffy May 31 '18 at 23:59
115

In the same spirit as 4ndrew's answer:

listOfNames="RA
RB
R C
RD"

# To allow for other whitespace in the string:
# 1. add double quotes around the list variable, or
# 2. see the IFS note (under 'Side Notes')

for databaseName in "$listOfNames"   #  <-- Note: Added "" quotes.
do
  echo "$databaseName"  # (i.e. do action / processing of $databaseName here...)
done

# Outputs
# RA
# RB
# R C
# RD

B. No whitespace in the names:

listOfNames="RA
RB
R C
RD"

for databaseName in $listOfNames  # Note: No quotes
do
  echo "$databaseName"  # (i.e. do action / processing of $databaseName here...)
done

# Outputs
# RA
# RB
# R
# C
# RD

Notes

  1. In the second example, using listOfNames="RA RB R C RD" has the same output.

Other ways to bring in data include:

Read from stdin

# line delimited (each databaseName is stored on a line)
while read databaseName
do
  echo "$databaseName"  # i.e. do action / processing of $databaseName here...
done # <<< or_another_input_method_here
  1. the bash IFS "field separator to line" [1] delimiter can be specified in the script to allow other whitespace (i.e. IFS='\n', or for MacOS IFS='\r')
  2. I like the accepted answer also :) -- I've include these snippets as other helpful ways that also answer the question.
  3. Including #!/bin/bash at the top of the script file indicates the execution environment.
  4. It took me months to figure out how to code this simply :)

Other Sources (while read loop)

Community
  • 1
  • 1
dajon
  • 2,350
  • 1
  • 16
  • 17
  • This creates impression that eol is used as string separators and, therefore, whitespaces are allowed within the strings. However, strings with whitespaces are further separated into substrings, which is very very bad. I think that this answer http://stackoverflow.com/a/23561892/1083704 is better. – Val Jul 11 '14 at 09:02
  • 1
    @Val, I added code comment with a reference to `IFS`. (For everyone, `IFS` lets one specify a specific delimiter, which allows other whitespace to be included in strings without being separated into substrings). – dajon Jul 21 '14 at 23:43
  • 11
    This doesn't work for me. `$databaseName` just contains the whole list, thus does only a single iteration. – AlikElzin-kilaka Jul 18 '16 at 13:04
  • @AlikElzin-kilaka My answer below solves this problem so that the loop is run for every line of the string. – Jamie Oct 16 '16 at 22:00
56

You can use the syntax of ${arrayName[@]}

#!/bin/bash
# declare an array called files, that contains 3 values
files=( "/etc/passwd" "/etc/group" "/etc/hosts" )
for i in "${files[@]}"
do
    echo "$i"
done
Fizer Khan
  • 88,237
  • 28
  • 143
  • 153
54

Surprised that nobody's posted this yet -- if you need the indices of the elements while you're looping through the array, you can do this:

arr=(foo bar baz)

for i in ${!arr[@]}
do
    echo $i "${arr[i]}"
done

Output:

0 foo
1 bar
2 baz

I find this a lot more elegant than the "traditional" for-loop style (for (( i=0; i<${#arr[@]}; i++ ))).

(${!arr[@]} and $i don't need to be quoted because they're just numbers; some would suggest quoting them anyway, but that's just personal preference.)

tckmn
  • 57,719
  • 27
  • 114
  • 156
  • 4
    This really should be the chosen answer. 1: It's simple and easy to read. 2: It handles whitespace correctly, no IFS nonsense is getting in the way. 3: It handles sparse arrays correctly. – mrm Dec 04 '19 at 20:58
  • @tckmn: is the exclamation mark (used twice) necessary? Seems to be wrong... – mirekphd Jul 23 '22 at 13:39
30

I used this approach for my GitHub updates, and I found it simple.

## declare an array variable
arr_variable=("kofi" "kwame" "Ama")

## now loop through the above array
for i in "${arr_variable[@]}"
do
   echo "$i"


done
   

You can iterate through bash array values using a counter with three-expression (C style) to read all values and indexes for loops syntax:

declare -a kofi=("kofi" "kwame" "Ama")
 
# get the length of the array
length=${#kofi[@]}

for (( j=0; j<${length}; j++ ));
do
  print (f "Current index %d with value %s\n" $j "${kofi[$j]}")
done
Kofi
  • 1,224
  • 1
  • 10
  • 21
  • 1
    a bash array can have holes in it; the correct way to loop through it by _index_ (that also works on associative arrays) is: `for i in "${!arr_variable[@]}"; do printf '%d: %s\n' "$i" "${arr_variable[i]}"; done` – Fravadona Jan 17 '22 at 16:42
28

This is also easy to read:

FilePath=(
    "/tmp/path1/"    #FilePath[0]
    "/tmp/path2/"    #FilePath[1]
)

#Loop
for Path in "${FilePath[@]}"
do
    echo "$Path"
done
  • 5
    This one is clear and worked for me (including with spaces and variable substitution in the FilePath array elements) only when I set the IFS variable correctly _before_ the FilePath array definition: `IFS=$'\n'` This may work for other solutions too in this scenario. – Alan Forsyth Jan 22 '16 at 12:41
13
listOfNames="db_one db_two db_three"
for databaseName in $listOfNames
do
  echo $databaseName
done

or just

for databaseName in db_one db_two db_three
do
  echo $databaseName
done
nroose
  • 1,689
  • 2
  • 21
  • 28
13

Simple way :

arr=("sharlock"  "bomkesh"  "feluda" )  ##declare array

len=${#arr[*]}  # it returns the array length

#iterate with while loop
i=0
while [ $i -lt $len ]
do
    echo ${arr[$i]}
    i=$((i+1))
done


#iterate with for loop
for i in $arr
do
  echo $i
done

#iterate with splice
 echo ${arr[@]:0:3}
rashedcs
  • 3,588
  • 2
  • 39
  • 40
11

Implicit array for script or functions:

In addition to anubhava's correct answer: If basic syntax for loop is:

for var in "${arr[@]}" ;do ...$var... ;done

there is a special case in :

When running a script or a function, arguments passed at command lines will be assigned to $@ array variable, you can access by $1, $2, $3, and so on.

This can be populated (for test) by

set -- arg1 arg2 arg3 ...

A loop over this array could be written simply:

for item ;do
    echo "This is item: $item."
  done

Note that the reserved work in is not present and no array name too!

Sample:

set -- arg1 arg2 arg3 ...
for item ;do
    echo "This is item: $item."
  done
This is item: arg1.
This is item: arg2.
This is item: arg3.
This is item: ....

Note that this is same than

for item in "$@";do
    echo "This is item: $item."
  done

Then into a script:

#!/bin/bash

for item ;do
    printf "Doing something with '%s'.\n" "$item"
  done

Save this in a script myscript.sh, chmod +x myscript.sh, then

./myscript.sh arg1 arg2 arg3 ...
Doing something with 'arg1'.
Doing something with 'arg2'.
Doing something with 'arg3'.
Doing something with '...'.

Same in a function:

myfunc() { for item;do cat <<<"Working about '$item'."; done ; }

Then

myfunc item1 tiem2 time3
Working about 'item1'.
Working about 'tiem2'.
Working about 'time3'.
F. Hauri - Give Up GitHub
  • 64,122
  • 17
  • 116
  • 137
7

The declare array doesn't work for Korn shell. Use the below example for the Korn shell:

promote_sla_chk_lst="cdi xlob"

set -A promote_arry $promote_sla_chk_lst

for i in ${promote_arry[*]};
    do
            echo $i
    done
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Bhanu
  • 97
  • 1
  • 1
  • 2
    try the code highlighter in the editor to make your code look good. – dove Nov 02 '12 at 19:39
  • 5
    Good to know, but this question is about bash. – Brad Koch May 20 '13 at 14:47
  • 1
    Lotsa bugs here. Can't have list entries with spaces, can't have list entries with glob characters. `for i in ${foo[*]}` is basically always the wrong thing -- `for i in "${foo[@]}"` is the form that preserves the original list's boundaries and prevents glob expansion. And the echo needs to be `echo "$i"` – Charles Duffy Jul 09 '16 at 15:00
7

Try this. It is working and tested.

for k in "${array[@]}"
do
    echo $k
done

# For accessing with the echo command: echo ${array[0]}, ${array[1]}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
SK.
  • 4,174
  • 4
  • 30
  • 48
  • 3
    This does not actually work correctly. Try `array=( "hello world" )`, or `arrray=( "*" )`; in the first case it will print `hello` and `world` separately, in the second it will print a list of files instead of the `*` – Charles Duffy Jul 09 '16 at 14:55
  • 7
    ...before calling something "tested" in shell, be sure to check the corner cases, which whitespace and globs are both among. – Charles Duffy Jul 09 '16 at 14:58
6

This is similar to user2533809's answer, but each file will be executed as a separate command.

#!/bin/bash
names="RA
RB
R C
RD"

while read -r line; do
    echo line: "$line"
done <<< "$names"
Jamie
  • 2,181
  • 1
  • 21
  • 35
4

If you are using Korn shell, there is "set -A databaseName ", else there is "declare -a databaseName"

To write a script working on all shells,

 set -A databaseName=("db1" "db2" ....) ||
        declare -a databaseName=("db1" "db2" ....)
# now loop 
for dbname in "${arr[@]}"
do
   echo "$dbname"  # or whatever

done

It should be work on all shells.

  • 3
    Nope, it doesn't: `$ bash --version` GNU bash, version 4.3.33(0)-release (amd64-portbld-freebsd10.0) `$ set -A databaseName=("db1" "db2" ....) || declare -a databaseName=("db1" "db2" ....)` bash: syntax error near unexpected token `(' – Bernie Reiter Jan 17 '17 at 19:47
4

What I really needed for this was something like this:

for i in $(the_array); do something; done

For instance:

for i in $(ps -aux | grep vlc  | awk '{ print $2 }'); do kill -9 $i; done

(Would kill all processes with vlc in their name)

Mahdi-Malv
  • 16,677
  • 10
  • 70
  • 117
3

Possible first line of every Bash script/session:

say() { for line in "${@}" ; do printf "%s\n" "${line}" ; done ; }

Use e.g.:

$ aa=( 7 -4 -e ) ; say "${aa[@]}"
7
-4
-e

May consider: echo interprets -e as option here

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
elf12
  • 69
  • 2
3

Single line looping,

 declare -a listOfNames=('db_a' 'db_b' 'db_c')
 for databaseName in ${listOfNames[@]}; do echo $databaseName; done;

you will get an output like this,

db_a
db_b
db_c
Mohideen bin Mohammed
  • 18,813
  • 10
  • 112
  • 118
3

How you loop through an array, depends on the presence of new line characters. With new line characters separating the array elements, the array can be referred to as "$array", otherwise it should be referred to as "${array[@]}". The following script will make it clear:

#!/bin/bash

mkdir temp
mkdir temp/aaa
mkdir temp/bbb
mkdir temp/ccc
array=$(ls temp)
array1=(aaa bbb ccc)
array2=$(echo -e "aaa\nbbb\nccc")

echo '$array'
echo "$array"
echo
for dirname in "$array"; do
    echo "$dirname"
done
echo
for dirname in "${array[@]}"; do
    echo "$dirname"
done
echo
echo '$array1'
echo "$array1"
echo
for dirname in "$array1"; do
    echo "$dirname"
done
echo
for dirname in "${array1[@]}"; do
    echo "$dirname"
done
echo
echo '$array2'
echo "$array2"
echo
for dirname in "$array2"; do
    echo "$dirname"
done
echo
for dirname in "${array2[@]}"; do
    echo "$dirname"
done
rmdir temp/aaa
rmdir temp/bbb
rmdir temp/ccc
rmdir temp
Dan Bray
  • 7,242
  • 3
  • 52
  • 70
2

I loop through an array of my projects for a git pull update:

#!/bin/sh
projects="
web
ios
android
"
for project in $projects do
    cd  $HOME/develop/$project && git pull
end
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
jiahut
  • 1,451
  • 15
  • 14
  • 7
    While this code snippet may solve the question, [including an explanation](//meta.stackexchange.com/questions/114762/explaining-entirely-code-based-answers) really helps to improve the quality of your post. Remember that you are answering the question for readers in the future, and those people might not know the reasons for your code suggestion. Please also try not to crowd your code with explanatory comments, this reduces the readability of both the code and the explanations! – kayess Dec 08 '16 at 08:37
  • you should explain ```IFS``` variable behavior in your script – Akhil Aug 21 '20 at 10:17