1

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>
4

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[@]}"
  • 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 Oct 27 '17 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? – Michael Daffin Oct 27 '17 at 14:00
  • 1
    Bash is not terrible at handling arrays. Users are terrible at handling Bash. – Kusalananda Oct 27 '17 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 @pkaramol – Michael Daffin Oct 27 '17 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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.