Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to assign a glob expression to a variable in a Bash script?

Tags:

bash

glob

When the following two lines of code are executed in a bash script, "ls" complains that the files don't exist:

dirs=/content/{dev01,dev02} ls -l $dirs 

When I run the script with the -x option, it appears to be passing the variable within single quotes (which would prevent globbing):

+ dirs=/content/{dev01,dev01} + ls -l '/content/{dev01,dev01}' ls: /content/{dev01,dev01}: No such file or directory 

If I execute the "ls" command from my interactive shell (sans quotes), it returns the two directories.

I've been reading through the Bash Reference Manual (v 3.2) and can't see any reason for filename globbing to not take place (I'm not passing -f to the shell), or anything that I can set to ensure that globbing happens.

like image 813
kdgregory Avatar asked Dec 15 '08 17:12

kdgregory


People also ask

How do I use glob in bash?

You can use '^' with square bracket to define globbing pattern more specifically. '^' can be used inside or outside of square bracket. '^' is used outside the square bracket to search those contents of the file that starts with a given range of characters.

How do you store output of ls command in a variable?

To store the output of a command in a variable, you can use the shell command substitution feature in the forms below: variable_name=$(command) variable_name=$(command [option ...] arg1 arg2 ...) OR variable_name='command' variable_name='command [option ...]

How do you set a global variable in bash?

The easiest way to set environment variables in Bash is to use the “export” keyword followed by the variable name, an equal sign and the value to be assigned to the environment variable.


2 Answers

I think it is the order of expansions:

The order of expansions is: brace expansion, tilde expansion, parameter, variable and arithmetic expansion and command substitution (done in a left-to-right fashion), word splitting, and pathname expansion.

So if your variable is substituted, brace expansion doesn't take place anymore. This works for me:

eval ls $dirs 

Be very careful with eval. It will execute the stuff verbatimly. So if dirs contains f{m,k}t*; some_command, some_command will be executed after the ls finished. It will execute the string you give to eval in the current shell. It will pass /content/dev01 /content/dev02 to ls, whether they exist or not. Putting * after the stuff makes it a pathname-expansion, and it will omit non-existing paths:

dirs=/content/{dev01,dev02}* 

I'm not 100% sure about this, but it makes sense to me.

like image 107
Johannes Schaub - litb Avatar answered Oct 01 '22 21:10

Johannes Schaub - litb


Here is an excellent discussion of what you are trying to do.

The short answer is that you want an array:

dirs=(/content/{dev01,dev01}) 

But what you do with the results can get more complex than what you were aiming for I think.

like image 21
feoh Avatar answered Oct 01 '22 22:10

feoh