5

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.

3
  • It not completely clear to me what you want. Did you try without all the quotes "?
    – Bernhard
    Feb 20, 2013 at 18:55
  • It works if that glob matches something. $HOME is usually the home directory. Are you setting $HOMEDIR manually?
    – jordanm
    Feb 20, 2013 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 Feb 20, 2013 at 19:16

2 Answers 2

8
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.

6
  • +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. Feb 20, 2013 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, 2013 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? Feb 21, 2013 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, 2013 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, 2013 at 4:08
0

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.

6
  • 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. Feb 21, 2013 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. Feb 21, 2013 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... Feb 21, 2013 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. Feb 21, 2013 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. Feb 21, 2013 at 3:40

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .