2

I am using the following script, so as to call a function that is supposed to iterate over an array.

#!/bin/bash function iterarr { for item in "$1" do echo "$item" done } myarr=(/dir1/file1.md /dir1/file2.md README.md) iterarr "${myarr[@]}" 

However, when I execute it, it gives the following output.

/dir1/file1.md

Why does it print only the first array entry?

edit: What is more, I would like to be able to use an additional argument (besides the array, so if I use '$@', how to I access the second argument?)

Working on Ubuntu 16.04.03 with ...

*$ $(which bash) --version GNU bash, version 4.3.48(1)-release (x86_64-pc-linux-gnu) Copyright (C) 2013 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> 

    2 Answers 2

    5

    iterarr "${myarr[@]}" will expand to iterarr '/dir1/file1.md' '/dir1/file2.md' 'README.md' and in your loop you only reference the first argument with "$1". Instead use "$@" to loop over all of the arguments.

    #!/bin/bash function iterarr { for item in "$@" do echo "$item" done } myarr=(/dir1/file1.md /dir1/file2.md README.md) iterarr "${myarr[@]}" 

    If you want to process flags, or positional arguments then place them before the array and handle them first, shifting them when done will remove them from "$@",

    #!/bin/bash function iterarr { echo "first argument is : '$1'" shift for item in "$@" do echo "$item" done } myarr=(/dir1/file1.md /dir1/file2.md README.md) iterarr firstarg "${myarr[@]}" 
    4
    • Thanks that worked. I also noticed that by keeping quotes both in "$@" and in function invocation, i.e. iterarr "${myarr[@]}", output is in a single line. By removing quotes in either of them, array elements are printed in separate lines. why is that?
      – pkaramol
      CommentedOct 27, 2017 at 13:48
    • Bash is terrible at handling arrays and you will have issues with spaces in the filenames if you leave them unquoted. But them all being printed out on one line suggests that the loop is treating them as one argument and only looping once - which is not what you want. My version of bash (4.4.12 on arch linux) works as expected and prints out all the entries on separate lines when both the array and $@ are quoted, which version are you running on what distro?CommentedOct 27, 2017 at 14:00
    • 1
      Bash is not terrible at handling arrays. Users are terrible at handling Bash.
      – Kusalananda
      CommentedOct 27, 2017 at 14:09
    • Works for me in a ubuntu 16.03 docker container as well, not sure why you are getting the behaviour described in your first comment @pkaramolCommentedOct 27, 2017 at 14:14
    1

    With this current version of bash, use a "nameref" to pass the array by name:

    iterarr() { local -n local_arr=$1 for item in "${local_arr[@]}"; do echo "$item"; done } myarr=(/dir1/file1.md /dir1/file2.md README.md) iterarr myarr 
    /dir1/file1.md /dir1/file2.md README.md 

      You must log in to answer this question.

      Start asking to get answers

      Find the answer to your question by asking.

      Ask question

      Explore related questions

      See similar questions with these tags.