Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I have this bash script which is trying to find a directory that partially changes on peoples systems.

cd "$HOMEDIR/AppData/Local/GitHub/PortableGit"*"/bin"

Yet this does not seem to work - it just take the string literal.

Is there an easy to make it expand correctly?

Edit:

Okay this is weird it works some of the time.

When I do this:

GIT_DIR=$HOMEDIR/AppData/Local/GitHub/PortableGit*/bin
eval GIT_DIR_PASS=$GIT_DIR
echo $GIT_DIR_PASS

I get the correct information out

but when I try to assign $GIT_DIR_PASS to another variable I get the string literal version.

share|improve this question
    
It not completely clear to me what you want. Did you try without all the quotes "? –  Bernhard Feb 20 '13 at 18:55
    
It works if that glob matches something. $HOME is usually the home directory. Are you setting $HOMEDIR manually? –  jordanm Feb 20 '13 at 18:55
    
I am setting the home directory manually. But I always get this error message. AppData/Local/GitHub/PortableGit*/bin : No such file or directory –  Ley Missailidis Feb 20 '13 at 19:16
add comment

2 Answers

Take a look at these examples to get a feeling for how to use wildcards in bash. Also, forget about the eval stuff.

A glob that would match all directories named /bin/ that are direct subdirectories of any direct subdirectory of .../PortableGit/:

HOMEDIR=/home/$USER
ls "$HOMEDIR/AppData/Local/GitHub/PortableGit/"*"/bin"

I think cd is your problem. What exactly do you expect it to do? If there is more than one directory matching your expression, it would be fruitless to call it that way, because cd will end up in the first matching directory, whatever you are planning on doing in there. If you want to sequentially enter directories do do stuff in them, then performing a loop over a conforming find output would seem more appropriate.

There is a similar question on stackoverflow.

share|improve this answer
1  
There is no reason to avoid quotes in glob expressions. Pathname Expansion is done after word splitting so the special chars "don't see" the quotes at all. –  Hauke Laging Feb 21 '13 at 2:26
    
Thank you for sharing that detail, I modified my answer to be of a less absolute tone. But: neither is there a reason to have quotes involved in glob expressions. If the quotes were around the wildcard, nothing would be expanded at all. This is why I kinda wanted to have them out of the way in this case. –  J. Katzwinkel Feb 21 '13 at 2:58
1  
You are even forced to use quotes if the glob expression contains metacharacters (like space). Do we know what $HOMEDIR looks like... –  Hauke Laging Feb 21 '13 at 3:01
    
You got me again. I edited accordingly and drew back even further. I hope you'll show the mercy of not proving me wrong another time. –  J. Katzwinkel Feb 21 '13 at 3:21
    
Your decision how much you want to learn today. :-) If you decide to learn more then I would point you at the fact that * doesn't match / so that your "any subdirectory" has to be understood as "any direct subdirectory". Maybe you meant that but I find the wording ambigious. –  Hauke Laging Feb 21 '13 at 3:40
show 1 more comment
GIT_DIR=$HOMEDIR/AppData/Local/GitHub/PortableGit*/bin

Above the wildcard is not expanded, because you're assigning to a scalar variable which can only contain one string, so no word splitting or filename generation take place there.

eval GIT_DIR_PASS=$GIT_DIR

Here, it's a an argument to a simple command, so wildcards are expanded but they would be expanded to files whose path is "GIT_DIR_PATH=...".

echo $GIT_DIR_PASS

Here the wildcards are expanded. You're not printing the content of the variable, but the list of arguments that result from the expansion since the variable is not quoted.

You'd want:

set -- "$HOMEDIR"/AppData/Local/GitHub/PortableGit*/bin

That is expand that pattern into the list of matching files and assign them to $1, $2...

GIT_DIR=$1

Pick the first one.

share|improve this answer
    
+1. I like the sugguestion to use set. Maybe you should have described a way to process its results, too. I still think Ley is intending something like for GIT_DIR in $*; do cd $GIT_DIR; dostuff; cd ~; done. Thank you for your informative answer. –  J. Katzwinkel Feb 20 '13 at 20:55
1  
@J.Katzwinkel Do not use $* (or even "$*"), it mangles your arguments into one (and will have wordsplitting performed on them as well if you don't quote it). Use "$@" instead, which preserves the arguments intact. –  Chris Down Feb 21 '13 at 2:57
    
Good point! I'm used not to having whitespace in file names, so I didn't think of word splitting. But to be honest, even on paths containing spaces, it doesn't really make a difference if I use $* or $@, quoted or not. We talking bash here? –  J. Katzwinkel Feb 21 '13 at 3:08
1  
@J.Katzwinkel Yes, we're talking bash, and yes it matters, as Chris Down said. $* and $@ will split all arguments by whitespace, so if $1 is a b and $2 is c, both will loop over a, b, and c; "$*" will loop over a b c (as a single string), but "$@" will correctly loop over a b and c. If you don't believe us, I suggest you open a terminal and try it out. –  Kevin Feb 21 '13 at 4:06
1  
Regardless, to go a step further, if you're looping over the positional variables ($1, $2, etc.), you don't even need the in part: for GIT_DIR; do cd $GIT_DIR; do_stuff; done. –  Kevin Feb 21 '13 at 4:08
show 1 more comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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