Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Assign results of globbing to a variable in Bash

Tags:

bash

glob

My colleague, Ryan, came to me with a bug in his Bash script, and I identified the problem with this test:

$ mkdir ryan $ mkdir ryan/smells-bad $ FOO=ryan/smells-* $ echo $FOO ryan/smells-bad $ touch $FOO/rotten_eggs touch: cannot touch `ryan/smells-*/rotten_eggs': No such file or directory 

From this I infer that the globbing happens during the echo command, not when the variable FOO is created.

We have a couple of workarounds, in descending order of ungracefulness:

touch `echo $FOO`/rotten_eggs 

Or:

pushd cd $FOO touch rotten_eggs popd 

But neither is satisfying. Am I missing a trick?

like image 746
Rob Fisher Avatar asked Feb 10 '12 15:02

Rob Fisher


People also ask

What is globbing in bash?

The Bash shell feature that is used for matching or expanding specific types of patterns is called globbing. Globbing is mainly used to match filenames or searching for content in a file. Globbing uses wildcard characters to create the pattern.

What does $_ mean in bash?

$_ (dollar underscore) is another special bash parameter and used to reference the absolute file name of the shell or bash script which is being executed as specified in the argument list. This bash parameter is also used to hold the name of mail file while checking emails.

How do I pass an environment variable in bash script?

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

The problem is that the glob will only expand if the file "rotten_eggs" exists, because it is included in the glob pattern. You should use an array.

FOO=( ryan/smells-* ) touch "${FOO[@]/%//rotten_eggs}" 

The FOO array contains everything matched by the glob. The expansion using % appends /rotten_eggs to each element.

like image 102
jordanm Avatar answered Sep 16 '22 12:09

jordanm


Consider

for dir in $FOO; do     touch "$dir/rotten_eggs" done 

Note that this will touch multiple files if the glob pattern matches more than one pathname.

like image 31
jilles Avatar answered Sep 19 '22 12:09

jilles