12

I'm struggling to execute a set of command lines stored as strings in an array. My code looks like this :

arr=( "sudo apt-get update" "sudo apt-get install xxx" )
...
arr=( ${arr[@]} "ln -s /path1 /path2" )
etc...

# Then I loop on the array of command 
for (( i = 0 ; i < ${#arr[@]} ; i++ ))
do
     eval ${arr[$i]}
done

When it loops over the array, the array is larger than the number of command stored into it. As if the blank spaces in my strings split the array in more elements A typical ouput is such like

usage: sudo -h | -K | -k | -L | -V

That means only 'sudo' is taken from within the string and I don't understand why!

Thanks

4
  • Can you show how loc_com is set/used? Commented Oct 14, 2011 at 21:28
  • as chown said, can you put an echo ${loc_com[$i]} before calling it. Commented Oct 14, 2011 at 21:45
  • Can you please post a test case that would conceivably work without editing? Commented Oct 14, 2011 at 21:46
  • 1
    @chown sorry, I made a mistake, it's 'arr' instead of 'loc_com,' and I missed a '#' in the loop as well Commented Oct 14, 2011 at 22:09

2 Answers 2

16

Use ${#arr[@]} to get the number of items in the array (${arr[@]} gives the word count). Using either eval or back-ticks (`) to execute the command works:

[ 15:20 jon@host ~ ]$ cat run_yum_test.sh
#!/bin/bash

declare -a arr=("sudo yum search zsh" "sudo yum list zsh")

for (( i = 0; i < ${#arr[@]} ; i++ )); do
    printf "\n**** Running: ${arr[$i]} *****\n\n"

    # Run each command in array 
    eval "${arr[$i]}"

    ### using back-ticks works also
    #RESULT=`${arr[$i]}`
    ### Check if the command gave any output
    #if [ -n "$RESULT" ]; then
    #    echo "$RESULT"
    #fi
done

[ 15:20 jon@host ~ ]$ ./run_yum_test.sh

**** Running: sudo yum search zsh *****

[sudo] password for jon:
Loaded plugins: presto, refresh-packagekit
=========================================================================== Matched: zsh ===========================================================================
zsh-html.i686 : Zsh shell manual in html format
autojump-zsh.noarch : Autojump for zsh
fatrat-czshare.i686 : FatRat plugin enabling CZShare.com downloads and uploads
gromacs-zsh.noarch : GROMACS zsh support
python-twisted-core-zsh.i686 : Tab completion for Zsh and Twisted Core
zsh.i686 : A powerful interactive shell
environment-modules.i686 : Provides dynamic modification of a user's environment
plowshare.noarch : CLI downloader/uploader for some of the most popular file-sharing websites

**** Running: sudo yum list zsh *****

Loaded plugins: presto, refresh-packagekit
Available Packages
zsh.i686                                                                    4.3.10-6.fc13                                                                    updates

Edit (to answer your comment):

To "extend" the array, put the original array (${arr[@]}) in quotes, like so:

arr=("sudo yum list zsh" "sudo yum search zsh")
arr=("${arr[@]}" "echo 'TEST'")

Here it is in action:

[ 16:06 jon@host ~ ]$ cat run_yum_test.sh
#!/bin/bash

arr=("sudo yum list zsh" "sudo yum search zsh")
arr=("${arr[@]}" "echo 'TEST'")

for (( i = 0; i < ${#arr[@]} ; i++ )); do
    printf "\n**** Running: ${arr[$i]} *****\n\n"
    eval "${arr[$i]}"
done


[ 16:06 jon@host ~ ]$ ./run_yum_test.sh

**** Running: sudo yum list zsh *****
[sudo] password for jon:
Loaded plugins: presto, refresh-packagekit
Available Packages
zsh.i686                                                                    4.3.10-6.fc13                                                                    updates

**** Running: sudo yum search zsh *****

Loaded plugins: presto, refresh-packagekit
=========================================================================== Matched: zsh ===========================================================================
zsh-html.i686 : Zsh shell manual in html format
autojump-zsh.noarch : Autojump for zsh
fatrat-czshare.i686 : FatRat plugin enabling CZShare.com downloads and uploads
gromacs-zsh.noarch : GROMACS zsh support
python-twisted-core-zsh.i686 : Tab completion for Zsh and Twisted Core
zsh.i686 : A powerful interactive shell
environment-modules.i686 : Provides dynamic modification of a user's environment
plowshare.noarch : CLI downloader/uploader for some of the most popular file-sharing websites

**** Running: echo 'TEST' *****

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

3 Comments

Right it's weird because it works for arr=("sudo apt-get update" "sudo apt-get upgrade") but not for arr=(); arr=(${arr[@]} "sudo ln -s $HOME/blabla /usr/bin/blabla"). It's always the same: the string is splitted and the shell makes an eval on each word...
@user996170 You need to put it in quotes, like this: arr=(); arr=("${arr[@]}" "sudo ln -s $HOME/blabla /usr/bin/blabla").
to append to an array, use the += operator: arr+=( "another command" )
0

I prefer this method:

#!/bin/bash

# Define your array of commands
commands=(
  "ls -l"
  "pwd"
  "echo Hello World!"
)

# Iterate and execute
for command in "${commands[@]}"; do
  eval "${command}"
done

Comments

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.