1

I have two folders under /tmp.

From terminal:

ls -d /tmp/firefox-* /tmp/firefox-sy2vakcj.default-esr-charlie-cache /tmp/firefox-sy2vakcj.default-esr-charlie-profile 

or

compgen -G /tmp/firefox-* /tmp/firefox-sy2vakcj.default-esr-charlie-cache /tmp/firefox-sy2vakcj.default-esr-charlie-profile 

And i can store the output in an array as well:

arr=( $(ls -d /tmp/firefox-*) ) echo $arr tmp/firefox-sy2vakcj.default-esr-charlie-cache /tmp/firefox-sy2vakcj.default-esr-charlie-profile echo $arr[1] tmp/firefox-sy2vakcj.default-esr-charlie-cache echo $arr[2] /tmp/firefox-sy2vakcj.default-esr-charlie-profile 

so far so good.

But if i attempt the same thing from a script:

 ... ... arr=( "$(ls -d /tmp/firefox-*)" ) ||( echo "directory doesn't exist" && exit 1) #arr=( "$(compgen -G /tmp/firefox-*)" ) ||( echo "directory doesn't exist" && exit 1) echo "this is a test for arr[1]: $arr[1]" echo "this is a test for arr[2]: $arr[2]" ... 

I get the output:

From script:

for ls -d this is the output:

+ arr=("$(ls -d /tmp/firefox-*)") ++ ls -d '/tmp/firefox-*' ls: cannot access '/tmp/firefox-*': No such file or directory + echo 'directory doesn'\''t exist' directory doesn't exist 

and for compgen -G , this is the output:

this is a test for arr[1]: /tmp/firefox-sy2vakcj.default-esr-charlie-cache /tmp/firefox-sy2vakcj.default-esr-charlie-profile[1] this is a test for arr[2]: /tmp/firefox-sy2vakcj.default-esr-charlie-cache /tmp/firefox-sy2vakcj.default-esr-charlie-profile[2] 

My questions:

1. Why is the glob not expanding in the subshell for the command ls -d ?

2. With compgen -G, how are the values being stored in the array? the output seems like each entry in the array is storing both the directory entry with the second one with its own index array?

3. Is the output from terminal for both commands different from the script, or am i missing something?

9
  • 2
    Why did you enclose the command substitution in double-quotes in your script? It would lead to the multi-word output being treated as one token (and hence only one array element). Also, array elements are referenced as ${arr[1]} - $arr[1] (as you can see) is the same as $arr followed by the literal string [1], and $arr when used on an array is equal to the first array element. I would recommend shellcheck to check for such errors.
    – AdminBee
    CommentedOct 19, 2021 at 9:30
  • Does this answer your question? Why does my shell script choke on whitespace or other special characters?
    – Wieland
    CommentedOct 19, 2021 at 9:34
  • 4
    that part with echo $arr and echo $arr[1] looks like zsh. Except for the part where the first array element is missing the leading slash. Check to make sure what shell you're running, and copypaste the complete commands and their complete output, and if you're asking about scripts, include the complete script, and the complete command line you use to run the script.
    – ilkkachu
    CommentedOct 19, 2021 at 9:41
  • 1
    @Wieland why would that answer the question? Is this related to quoting and whitespace? How?
    – terdon
    CommentedOct 19, 2021 at 9:46
  • Are you maybe using macOS? That has a default shell of zsh which would explain part of what you're showing here as ilkkackhu pointed out.
    – terdon
    CommentedOct 19, 2021 at 9:46

1 Answer 1

1
  1. Why is the glob not expanding in the subshell for the command ls -d ?

You've probably turned off globbing by using set -f. To demonstrate:

$ touch firefox-1 firefox-2 $ arr=( firefox-* ); declare -p arr declare -a arr=([0]="firefox-1" [1]="firefox-2") $ set -f $ arr=( firefox-* ); declare -p arr declare -a arr=([0]="firefox-*") 
  1. With compgen -G, how are the values being stored in the array? the output seems like each entry in the array is storing both the directory entry with the second one with its own index array?

When you do arr=( "$(compgen -G /tmp/firefox-*)" ), the double quotes force the compgen output to be stored as a single element in the array. In this case, to read the lines of output into an array, use mapfile with a process substitution:

$ mapfile -t arr < <(compgen -G ./firefox-*) $ declare -p arr declare -a arr=([0]="./firefox-1" [1]="./firefox-2") 
  1. Is the output from terminal for both commands different from the script, or am i missing something?

Looks like your interactive shell is zsh. Aside from that, you're missing the parameter expansion syntax for array elements requiring the braces (3.5.3 Shell Parameter Expansion), and that bash arrays are indexed starting from zero:

echo "${arr[0]}" 

    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.