Spaces in Linux environmental variables?
Solution 1
The problem is not that your environmental variable contains a space. You're forgetting to quote your arguments:
cd "$Foo"
If you don't quote $Foo
, the cd
command will actually see two (or more) arguments, since whitespace by default separates arguments. In your specific case, you'd pass /media/foo/can
and haz/bar
separately, since the shell splits them at the space. Double-quoting variables is a good habit to develop, and will save you in quite a lot of cases where whitespace is involved.
If you want a really ugly way of achieving this without quotes, overwrite your cd
builtin like so:
cd() { builtin cd "$*"; }
This will work if the path contains spaces, since $*
will contain the individual arguments (/media/foo/can
and haz/bar
), separated by the first IFS character (usually a space), and then you'll glue them together with the double quotes.
It is never a good idea to overwrite builtins like this, though.
Solution 2
As @slhck said, the correct way to do this is to put double-quotes around the variable reference (e.g. cd "$Foo"
). The reason for this is the order that the shell parses various aspects of the command line: first it scans for quotes and escapes (and removes them as it applies their effects), then it replaces variable references with their values (e.g. $Foo
-> /media/foo/can haz/bar
), then it goes back through the replaced values and applies wildcard expansion (*.txt
-> a.txt b.txt
etc) and word splitting (/media/foo/can haz/bar
-> "/media/foo/can" "haz/bar"), but it never goes back and looks for quotes and/or escapes in the variable values. As a result, embedding quotes and/or escapes in the value of a variable does nothing even slightly useful; by the time they're part of the command line, it's too late for them to have the intended effect. I only know of three ways to avoid word splitting on the expanded value:
- Double-quote the variable reference. It's not as convenient, but it's a requirement of standard shell syntax.
- Change the value of IFS (the list of characters that're used for word splitting on expanded variables). Then watch as all the scripts that depend on the standard word splitting behavior break weirdly. Please don't do this. Seriously.
- Switch to a shell that doesn't do word splitting on expanded variables: zsh. You'll have to get used to its other differences from bash, but if you really want this, it's the best way to go. I don't use it myself, but those who do seem to like it a lot...
Related videos on Youtube
A T
Updated on September 18, 2022Comments
-
A T almost 2 years
Given directory:
/media/foo/can haz/bar
, I have tried editing bash.rc with:export Foo=/media/foo/can haz/bar export Foo=/media/foo/can\ haz/bar export Foo='/media/foo/can haz/bar' export Foo="/media/foo/can haz/bar" export Foo='"/media/foo/can haz/bar"' export Foo="'/media/foo/can haz/bar'"
Each time though, I couldn't get something like the following to work (without using
"$Foo"
):cd $Foo
How do I set an environmental variable with spaces on a Linux system?
-
A T almost 11 yearsMaybe if I set an alias or something?
-
-
A T almost 11 yearsAs mentioned, I want to avoid doing that; that is the whole problem I am trying to solve.
-
slhck almost 11 yearsDid you sneak that part in? I don't remember it being there in the first revision of the question I saw :) Anyhow, your question is, "How do I set an environmental variable with a space?", and the answer is, you can just do it. How you handle it is a different problem, and that you couldn't get it to work without quotes is just a matter of how the shell works.
-
slhck almost 11 yearsZsh also nicely auto-completes
cd $Foo
tocd /path\ with/spaces
. I've found Bash to do this wrongly if you trigger it withCtrl-A-E
, but I haven't used Bash in a while, so it might be possible to configure this as well. -
slhck almost 11 years@AT Have you seen my update?