0

It is known that parsing the output of ls is generally a bad idea and one solution is to use globbing instead of ls to 'safely' loop through files in a directory.

for path in /path/to/search/*; do
    ...
    # Do more filtering
    ...
    echo "$path"
done

This function will further filter some of the results that the glob matches and outputs the remaining paths.

However if I want to reuse this logic elsewhere can I use it's output via a function safely and loop that?

function myglob() {
    for path in /path/to/search/*; do
        ...
        # Do more filtering
        ...
        echo "$path"
    done
}

function myExample() {
    results=$(myglob)
    for i in "$results"; do
        echo "$i"
    done
}

Or must I always duplicate the glob logic and make minor changes to the logic inside?

1

No, you can't reuse the loops output as you have show as that replicates the issue with ls exactly, as well as adds issues with echo possibly interpreting backslashes in filenames.

Instead, if you're using a shell language that has arrays and name references (like in bash 4.3+), you can do it slightly differently:

myglob () {
   declare -n list="$1"

   list=( /path/to/search/* )
}

myexample () {
    local results=()
    myglob results

    for pathname in "${results[@]}"; do
        printf '%s\n' "$pathname"
    done

    # or shorter, just
    # printf '%s\n' "${results[@]}"
}

Here, the myglob function takes the name of a variable in list, which is a name reference variable. This means that any use of list will in fact use the named variable. The function simply expands the glob and stores the result in list as if it was an array.

The myexample function then calls myglob with the string results. The list variable in myglob will therefore reference the results variable, and store the expanded pattern in it.

The function then goes on to use results as an array of items.

If myglob needs to do filtering:

myglob () {
    declare -n list="$1"

    list=()
    for pathname in /path/to/search/*; do
        # decide whether to use "$pathname" or not
        # then, if it is to be used,
        list+=( "$pathname" )
    done
}

That is, loop over the expanded pattern and append items to the list if they are to be returned to the caller.

| improve this answer | |
  • I can understand the issue repeating when using printf or echo -e but I thought echo without the -e flag would not interpret the special chars like return etc? Is this not the case? – myol Nov 28 '19 at 11:15
  • 1
    @myol It depends. See Why is printf better than echo? – Kusalananda Nov 28 '19 at 11:19

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.