How Can I Expand A Tilde ~ As Part Of A Variable?cp command saying directory does not exist when it doesWhy...
My previous employer committed a severe violation of the law and is also being sued by me. How do I explain the situation to future employers?
Can one block with a protection from color creature?
What does "spinning upon the shoals" mean?
Can a landlord force all residents to use the landlord's in-house debit card accounts?
How should I ask for a "pint" in countries that use metric?
QR codes, do people use them?
Users forgotting to regenerate PDF before sending it
US citizen traveling with Peruvian passport
Is it possible to complete a PhD in CS in 3 years?
Is "wissen" the only verb in German to have an irregular present tense?
How to "add vert" in blender 2.8?
What was the nature of the known bugs in the Space Shuttle software?
Passwordless authentication - how and when to invalidate a login code
What factors could lead to bishops establishing monastic armies?
Interpretation of non-significant results as "trends"
Is there a method for differentiating informative comments from commented out code?
Writing an ace/aro character?
My professor has told me he will be the corresponding author. Will it hurt my future career?
How do I explain that I don't want to maintain old projects?
Is it ok for parents to kiss and romance with each other while their 2- to 8-year-old child watches?
How do resistors generate different heat if we make the current fixed and changed the voltage and resistance? Notice the flow of charge is constant
stuck {in/at} beta
Why did Old English lose both thorn and eth?
Why am I getting unevenly-spread results when using $RANDOM?
How Can I Expand A Tilde ~ As Part Of A Variable?
cp command saying directory does not exist when it doesWhy can't execute ls or cp commands with a variable as an argumentWhy doesn't the tilde (~) expand inside double quotes?Any problem assigning one variable to another in shell without using quotes?Do I need to quote command substitutions when assigning their output to a variable?using tilde in variable from the userreading input in sedattempting to put dynamic input data in a variable via cat methodWhy can I change bash history?BASH: Using awk to filter unique lines results in 0 length arrayWhat's the correct way to pass a variable as an argument to another command?Create new array with unique values from existing arrayCan't pipe from echo to bash built-in read?Set comparator with variables within a variable, then have shell expand those variables each time it's echo'dShell Script: how to expand a variable into quotesBash terminal trying to read a previously installed file on each start up
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ margin-bottom:0;
}
When I open up a bash prompt and type:
$ set -o xtrace
$ x='~/someDirectory'
+ x='~/someDirectory'
$ echo $x
+ echo '~/someDirectory'
~/someDirectory
I was hoping that the 5th line above would have went + echo /home/myUsername/someDirectory
. Is there a way to do this? In my original Bash script, the variable x is actually being populated from data from an input file, via a loop like this:
while IFS= read line
do
params=($line)
echo ${params[0]}
done <"./someInputFile.txt"
Still, I'm getting a similar result, with the echo '~/someDirectory'
instead of echo /home/myUsername/someDirectory
.
bash shell-script shell quoting variable
|
show 2 more comments
When I open up a bash prompt and type:
$ set -o xtrace
$ x='~/someDirectory'
+ x='~/someDirectory'
$ echo $x
+ echo '~/someDirectory'
~/someDirectory
I was hoping that the 5th line above would have went + echo /home/myUsername/someDirectory
. Is there a way to do this? In my original Bash script, the variable x is actually being populated from data from an input file, via a loop like this:
while IFS= read line
do
params=($line)
echo ${params[0]}
done <"./someInputFile.txt"
Still, I'm getting a similar result, with the echo '~/someDirectory'
instead of echo /home/myUsername/someDirectory
.
bash shell-script shell quoting variable
In ZSH this isx='~'; print -l ${x} ${~x}
. I gave up after digging through thebash
manual for a while.
– thrig
Oct 20 '17 at 19:02
@thrig: This is not a bashism, this behavior is POSIX.
– WhiteWinterWolf
Oct 20 '17 at 21:35
Extremely closely related (if not a dupe): unix.stackexchange.com/questions/151850/…
– Kusalananda♦
Oct 20 '17 at 21:42
@Kusalananda: I'm not sure this is a dupe as the reason here is somewhat different: the OP did not enclose $x between quotes when echoing it.
– WhiteWinterWolf
Oct 20 '17 at 21:55
You don't put tildes in the input file. Problem solved.
– chepner
Oct 21 '17 at 1:24
|
show 2 more comments
When I open up a bash prompt and type:
$ set -o xtrace
$ x='~/someDirectory'
+ x='~/someDirectory'
$ echo $x
+ echo '~/someDirectory'
~/someDirectory
I was hoping that the 5th line above would have went + echo /home/myUsername/someDirectory
. Is there a way to do this? In my original Bash script, the variable x is actually being populated from data from an input file, via a loop like this:
while IFS= read line
do
params=($line)
echo ${params[0]}
done <"./someInputFile.txt"
Still, I'm getting a similar result, with the echo '~/someDirectory'
instead of echo /home/myUsername/someDirectory
.
bash shell-script shell quoting variable
When I open up a bash prompt and type:
$ set -o xtrace
$ x='~/someDirectory'
+ x='~/someDirectory'
$ echo $x
+ echo '~/someDirectory'
~/someDirectory
I was hoping that the 5th line above would have went + echo /home/myUsername/someDirectory
. Is there a way to do this? In my original Bash script, the variable x is actually being populated from data from an input file, via a loop like this:
while IFS= read line
do
params=($line)
echo ${params[0]}
done <"./someInputFile.txt"
Still, I'm getting a similar result, with the echo '~/someDirectory'
instead of echo /home/myUsername/someDirectory
.
bash shell-script shell quoting variable
bash shell-script shell quoting variable
asked Oct 20 '17 at 18:34
AndrewAndrew
1381 silver badge5 bronze badges
1381 silver badge5 bronze badges
In ZSH this isx='~'; print -l ${x} ${~x}
. I gave up after digging through thebash
manual for a while.
– thrig
Oct 20 '17 at 19:02
@thrig: This is not a bashism, this behavior is POSIX.
– WhiteWinterWolf
Oct 20 '17 at 21:35
Extremely closely related (if not a dupe): unix.stackexchange.com/questions/151850/…
– Kusalananda♦
Oct 20 '17 at 21:42
@Kusalananda: I'm not sure this is a dupe as the reason here is somewhat different: the OP did not enclose $x between quotes when echoing it.
– WhiteWinterWolf
Oct 20 '17 at 21:55
You don't put tildes in the input file. Problem solved.
– chepner
Oct 21 '17 at 1:24
|
show 2 more comments
In ZSH this isx='~'; print -l ${x} ${~x}
. I gave up after digging through thebash
manual for a while.
– thrig
Oct 20 '17 at 19:02
@thrig: This is not a bashism, this behavior is POSIX.
– WhiteWinterWolf
Oct 20 '17 at 21:35
Extremely closely related (if not a dupe): unix.stackexchange.com/questions/151850/…
– Kusalananda♦
Oct 20 '17 at 21:42
@Kusalananda: I'm not sure this is a dupe as the reason here is somewhat different: the OP did not enclose $x between quotes when echoing it.
– WhiteWinterWolf
Oct 20 '17 at 21:55
You don't put tildes in the input file. Problem solved.
– chepner
Oct 21 '17 at 1:24
In ZSH this is
x='~'; print -l ${x} ${~x}
. I gave up after digging through the bash
manual for a while.– thrig
Oct 20 '17 at 19:02
In ZSH this is
x='~'; print -l ${x} ${~x}
. I gave up after digging through the bash
manual for a while.– thrig
Oct 20 '17 at 19:02
@thrig: This is not a bashism, this behavior is POSIX.
– WhiteWinterWolf
Oct 20 '17 at 21:35
@thrig: This is not a bashism, this behavior is POSIX.
– WhiteWinterWolf
Oct 20 '17 at 21:35
Extremely closely related (if not a dupe): unix.stackexchange.com/questions/151850/…
– Kusalananda♦
Oct 20 '17 at 21:42
Extremely closely related (if not a dupe): unix.stackexchange.com/questions/151850/…
– Kusalananda♦
Oct 20 '17 at 21:42
@Kusalananda: I'm not sure this is a dupe as the reason here is somewhat different: the OP did not enclose $x between quotes when echoing it.
– WhiteWinterWolf
Oct 20 '17 at 21:55
@Kusalananda: I'm not sure this is a dupe as the reason here is somewhat different: the OP did not enclose $x between quotes when echoing it.
– WhiteWinterWolf
Oct 20 '17 at 21:55
You don't put tildes in the input file. Problem solved.
– chepner
Oct 21 '17 at 1:24
You don't put tildes in the input file. Problem solved.
– chepner
Oct 21 '17 at 1:24
|
show 2 more comments
2 Answers
2
active
oldest
votes
The POSIX standard imposes word expansion to be done in the following order (emphasize is mine):
Tilde expansion (see Tilde Expansion), parameter expansion (see Parameter Expansion), command substitution (see Command Substitution),
and arithmetic expansion (see Arithmetic Expansion) shall be
performed, beginning to end. See item 5 in Token Recognition.
Field splitting (see Field Splitting) shall be performed on the portions of the fields generated by step 1, unless IFS is null.
Pathname expansion (see Pathname Expansion) shall be performed, unless set -f is in effect.
Quote removal (see Quote Removal) shall always be performed last.
The only point which interests us here is the first one: as you can see tilde expansion is processed before parameter expansion:
- The shell attempts a tilde expansion on
echo $x
, there is no tilde to be found, so it proceeds. - The shell attempts a parameter expansion on
echo $x
,$x
is found and expanded and the command-line becomesecho ~/someDirectory
. - Processing continues, tilde expansion having already been processed the
~
character remains as-is.
By using the quotes while assigning the $x
, you were explicitly requesting to not expand the tilde and treat it like a normal character. A thing often missed is that in shell commands you don't have to quote the whole string, so you can make the expansion happen right during the variable assignment:
user@host:~$ set -o xtrace
user@host:~$ x=~/'someDirectory'
+ x=/home/user/someDirectory
user@host:~$ echo $x
+ echo /home/user/someDirectory
/home/user/someDirectory
user@host:~$
And you can also make the expansion occur on the echo
command-line as long as it can happen before parameter expansion:
user@host:~$ x='someDirectory'
+ x=someDirectory
user@host:~$ echo ~/$x
+ echo /home/user/someDirectory
/home/user/someDirectory
user@host:~$
If for some reason you really need to affect the tilde to the $x
variable without expansion, and be able to expand it at the echo
command, you must proceed in two times to force two expansions of the $x
variable to occur:
user@host:~$ x='~/someDirectory'
+ x='~/someDirectory'
user@host:~$ echo "$( eval echo $x )"
++ eval echo '~/someDirectory'
+++ echo /home/user/someDirectory
+ echo /home/user/someDirectory
/home/user/someDirectory
user@host:~$
However, be aware that depending on the context where you use such structure it may have unwanted side-effect. As a rule of thumb, prefer to avoid using anything requiring eval
when you have another way.
If you want to specifically address the tilde issue as opposed to any other kind of expansion, such structure would be safer and portable:
user@host:~$ x='~/someDirectory'
+ x='~/someDirectory'
user@host:~$ case "$x" in "~/"*)
> x="${HOME}/${x#"~/"}"
> esac
+ case "$x" in
+ x=/home/user/someDirectory
user@host:~$ echo $x
+ echo /home/user/someDirectory
/home/user/someDirectory
user@host:~$
This structure explicitly check the presence of a leading ~
and replaces it with the user home dir if it is found.
Following your comment, the x="${HOME}/${x#"~/"}"
may indeed be surprising for someone not used in shell programming, but is in fact linked to the same POSIX rule I quoted above.
As imposed by the POSIX standard, quote removal happens last and parameter expansion happens very early. Thus, ${#"~"}
is evaluated and expanded far before the evaluation of the outer quotes. In turns, as defined in Parameter expansion rules:
In each case that a value of word is needed (based on the state of
parameter, as described below), word shall be subjected to tilde
expansion, parameter expansion, command substitution, and arithmetic
expansion.
Thus, the right side of the #
operator must be properly quoted or escaped to avoid tilde expansion.
So, to state it differently, when the shell interpretor looks at x="${HOME}/${x#"~/"}"
, he sees:
${HOME}
and${x#"~/"}
must be expanded.
${HOME}
is expanded to the content of the$HOME
variable.
${x#"~/"}
triggers a nested expansion:"~/"
is parsed but, being quoted, is treated as a literal1. You could have used single quotes here with the same result.
${x#"~/"}
expression itself is now expanded, resulting in the prefix~/
being removed from the value of$x
.- The result of the above is now concatenated: the expansion of
${HOME}
, the literal/
, the expansion${x#"~/"}
. - The end-result is enclosed in double-quotes, functionally preventing word splitting. I say functionally here because these double quotes are not technically required (see here and there for instance), but as a personal style as soon as an assignments gets anything beyond
a=$b
I usually find it clearer add double-quotes.
By-the-way, if look more closely to the case
syntax, you will see the "~/"*
construction which relies on the same concept as x=~/'someDirectory'
I explained above (here again, double and simple quotes could be used interchangeably).
Don't worry if these things may seem obscure at the first sight (maybe even at the second or later sights!). In my opinion, parameter expansion are, with subshells, one of the most complex concept to grasp when programming in shell language.
I know that some people may vigorously disagree, but if you would-like to learn shell programming more in depth I encourage you to read the Advanced Bash Scripting Guide: it teaches Bash-scripting, so with a lot of extensions and bells-and-whistles compared to POSIX shell scripting, but I found it well written with loads of practical examples. Once you manage this, it is easy to restrict yourself to POSIX features when you need to, I personally think that entering directly in the POSIX realm is an unnecessary steep learning curve for beginners (compare my POSIX tilde replacement with @m0dular's regex-like Bash equivalent to get an idea of what I mean ;) !).
1: Which leads me into finding a bug in Dash which don't implement tilde expansion here correctly (verifiable using x='~/foo'; echo "${x#~/}"
). Parameter expansion is a complex field both for the user and the shell developers themselves!
How is the bash shell parsing the linex="${HOME}/${x#"~/"}"
? It looks like a concatenation of 3 strings:"${HOME}/${x#"
,~/
, and"}"
. Does the shell allow for nested double-quotes when the inner pair of double quotes is inside a${ }
block?
– Andrew
Oct 21 '17 at 2:35
@Andrew: I have complete my answer with additional information hopefully addressing your comment.
– WhiteWinterWolf
Oct 21 '17 at 8:41
Thanks, this is a great answer. I've learned a ton from reading it. Wish I could upvote it more than once:)
– Andrew
Oct 21 '17 at 14:03
@WhiteWinterWolf: still, shell does not see the nested quotes whatever the result is.
– avp
Nov 22 '18 at 10:15
add a comment |
One possible answer:
eval echo "$x"
Since you're reading input from a file, I would not do this.
You could search and replace the ~ with the value of $HOME, like this:
x='~/.config'
x="${x//~/$HOME}"
echo "$x"
Gives me:
/home/adrian/.config
Note that the${parameter/pattern/string}
expansion is a Bash extension and may not be available in other shells.
– WhiteWinterWolf
Oct 20 '17 at 21:53
True. The OP did mention he was using Bash, so I think it's an appropriate answer.
– m0dular
Oct 20 '17 at 22:06
I agree, as long as one is sticking to Bash why not fully take advantage of it (not everybody need portability everywhere), but it's just worth to note it for non-Bash users (several distro now ship with Dash instead of Bash for instance) so affected users are not surprised.
– WhiteWinterWolf
Oct 20 '17 at 22:13
I took the liberty to mention your post in my digression about differences between Bash extensions and POSIX shell scripting, as I think that your Bash single-line regex-like statement compared to my POSIXcase
structure illustrate well how Bash scripting is more user-friendly specially for beginners.
– WhiteWinterWolf
Oct 21 '17 at 8:43
add a comment |
Your Answer
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "106"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f399407%2fhow-can-i-expand-a-tilde-as-part-of-a-variable%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
The POSIX standard imposes word expansion to be done in the following order (emphasize is mine):
Tilde expansion (see Tilde Expansion), parameter expansion (see Parameter Expansion), command substitution (see Command Substitution),
and arithmetic expansion (see Arithmetic Expansion) shall be
performed, beginning to end. See item 5 in Token Recognition.
Field splitting (see Field Splitting) shall be performed on the portions of the fields generated by step 1, unless IFS is null.
Pathname expansion (see Pathname Expansion) shall be performed, unless set -f is in effect.
Quote removal (see Quote Removal) shall always be performed last.
The only point which interests us here is the first one: as you can see tilde expansion is processed before parameter expansion:
- The shell attempts a tilde expansion on
echo $x
, there is no tilde to be found, so it proceeds. - The shell attempts a parameter expansion on
echo $x
,$x
is found and expanded and the command-line becomesecho ~/someDirectory
. - Processing continues, tilde expansion having already been processed the
~
character remains as-is.
By using the quotes while assigning the $x
, you were explicitly requesting to not expand the tilde and treat it like a normal character. A thing often missed is that in shell commands you don't have to quote the whole string, so you can make the expansion happen right during the variable assignment:
user@host:~$ set -o xtrace
user@host:~$ x=~/'someDirectory'
+ x=/home/user/someDirectory
user@host:~$ echo $x
+ echo /home/user/someDirectory
/home/user/someDirectory
user@host:~$
And you can also make the expansion occur on the echo
command-line as long as it can happen before parameter expansion:
user@host:~$ x='someDirectory'
+ x=someDirectory
user@host:~$ echo ~/$x
+ echo /home/user/someDirectory
/home/user/someDirectory
user@host:~$
If for some reason you really need to affect the tilde to the $x
variable without expansion, and be able to expand it at the echo
command, you must proceed in two times to force two expansions of the $x
variable to occur:
user@host:~$ x='~/someDirectory'
+ x='~/someDirectory'
user@host:~$ echo "$( eval echo $x )"
++ eval echo '~/someDirectory'
+++ echo /home/user/someDirectory
+ echo /home/user/someDirectory
/home/user/someDirectory
user@host:~$
However, be aware that depending on the context where you use such structure it may have unwanted side-effect. As a rule of thumb, prefer to avoid using anything requiring eval
when you have another way.
If you want to specifically address the tilde issue as opposed to any other kind of expansion, such structure would be safer and portable:
user@host:~$ x='~/someDirectory'
+ x='~/someDirectory'
user@host:~$ case "$x" in "~/"*)
> x="${HOME}/${x#"~/"}"
> esac
+ case "$x" in
+ x=/home/user/someDirectory
user@host:~$ echo $x
+ echo /home/user/someDirectory
/home/user/someDirectory
user@host:~$
This structure explicitly check the presence of a leading ~
and replaces it with the user home dir if it is found.
Following your comment, the x="${HOME}/${x#"~/"}"
may indeed be surprising for someone not used in shell programming, but is in fact linked to the same POSIX rule I quoted above.
As imposed by the POSIX standard, quote removal happens last and parameter expansion happens very early. Thus, ${#"~"}
is evaluated and expanded far before the evaluation of the outer quotes. In turns, as defined in Parameter expansion rules:
In each case that a value of word is needed (based on the state of
parameter, as described below), word shall be subjected to tilde
expansion, parameter expansion, command substitution, and arithmetic
expansion.
Thus, the right side of the #
operator must be properly quoted or escaped to avoid tilde expansion.
So, to state it differently, when the shell interpretor looks at x="${HOME}/${x#"~/"}"
, he sees:
${HOME}
and${x#"~/"}
must be expanded.
${HOME}
is expanded to the content of the$HOME
variable.
${x#"~/"}
triggers a nested expansion:"~/"
is parsed but, being quoted, is treated as a literal1. You could have used single quotes here with the same result.
${x#"~/"}
expression itself is now expanded, resulting in the prefix~/
being removed from the value of$x
.- The result of the above is now concatenated: the expansion of
${HOME}
, the literal/
, the expansion${x#"~/"}
. - The end-result is enclosed in double-quotes, functionally preventing word splitting. I say functionally here because these double quotes are not technically required (see here and there for instance), but as a personal style as soon as an assignments gets anything beyond
a=$b
I usually find it clearer add double-quotes.
By-the-way, if look more closely to the case
syntax, you will see the "~/"*
construction which relies on the same concept as x=~/'someDirectory'
I explained above (here again, double and simple quotes could be used interchangeably).
Don't worry if these things may seem obscure at the first sight (maybe even at the second or later sights!). In my opinion, parameter expansion are, with subshells, one of the most complex concept to grasp when programming in shell language.
I know that some people may vigorously disagree, but if you would-like to learn shell programming more in depth I encourage you to read the Advanced Bash Scripting Guide: it teaches Bash-scripting, so with a lot of extensions and bells-and-whistles compared to POSIX shell scripting, but I found it well written with loads of practical examples. Once you manage this, it is easy to restrict yourself to POSIX features when you need to, I personally think that entering directly in the POSIX realm is an unnecessary steep learning curve for beginners (compare my POSIX tilde replacement with @m0dular's regex-like Bash equivalent to get an idea of what I mean ;) !).
1: Which leads me into finding a bug in Dash which don't implement tilde expansion here correctly (verifiable using x='~/foo'; echo "${x#~/}"
). Parameter expansion is a complex field both for the user and the shell developers themselves!
How is the bash shell parsing the linex="${HOME}/${x#"~/"}"
? It looks like a concatenation of 3 strings:"${HOME}/${x#"
,~/
, and"}"
. Does the shell allow for nested double-quotes when the inner pair of double quotes is inside a${ }
block?
– Andrew
Oct 21 '17 at 2:35
@Andrew: I have complete my answer with additional information hopefully addressing your comment.
– WhiteWinterWolf
Oct 21 '17 at 8:41
Thanks, this is a great answer. I've learned a ton from reading it. Wish I could upvote it more than once:)
– Andrew
Oct 21 '17 at 14:03
@WhiteWinterWolf: still, shell does not see the nested quotes whatever the result is.
– avp
Nov 22 '18 at 10:15
add a comment |
The POSIX standard imposes word expansion to be done in the following order (emphasize is mine):
Tilde expansion (see Tilde Expansion), parameter expansion (see Parameter Expansion), command substitution (see Command Substitution),
and arithmetic expansion (see Arithmetic Expansion) shall be
performed, beginning to end. See item 5 in Token Recognition.
Field splitting (see Field Splitting) shall be performed on the portions of the fields generated by step 1, unless IFS is null.
Pathname expansion (see Pathname Expansion) shall be performed, unless set -f is in effect.
Quote removal (see Quote Removal) shall always be performed last.
The only point which interests us here is the first one: as you can see tilde expansion is processed before parameter expansion:
- The shell attempts a tilde expansion on
echo $x
, there is no tilde to be found, so it proceeds. - The shell attempts a parameter expansion on
echo $x
,$x
is found and expanded and the command-line becomesecho ~/someDirectory
. - Processing continues, tilde expansion having already been processed the
~
character remains as-is.
By using the quotes while assigning the $x
, you were explicitly requesting to not expand the tilde and treat it like a normal character. A thing often missed is that in shell commands you don't have to quote the whole string, so you can make the expansion happen right during the variable assignment:
user@host:~$ set -o xtrace
user@host:~$ x=~/'someDirectory'
+ x=/home/user/someDirectory
user@host:~$ echo $x
+ echo /home/user/someDirectory
/home/user/someDirectory
user@host:~$
And you can also make the expansion occur on the echo
command-line as long as it can happen before parameter expansion:
user@host:~$ x='someDirectory'
+ x=someDirectory
user@host:~$ echo ~/$x
+ echo /home/user/someDirectory
/home/user/someDirectory
user@host:~$
If for some reason you really need to affect the tilde to the $x
variable without expansion, and be able to expand it at the echo
command, you must proceed in two times to force two expansions of the $x
variable to occur:
user@host:~$ x='~/someDirectory'
+ x='~/someDirectory'
user@host:~$ echo "$( eval echo $x )"
++ eval echo '~/someDirectory'
+++ echo /home/user/someDirectory
+ echo /home/user/someDirectory
/home/user/someDirectory
user@host:~$
However, be aware that depending on the context where you use such structure it may have unwanted side-effect. As a rule of thumb, prefer to avoid using anything requiring eval
when you have another way.
If you want to specifically address the tilde issue as opposed to any other kind of expansion, such structure would be safer and portable:
user@host:~$ x='~/someDirectory'
+ x='~/someDirectory'
user@host:~$ case "$x" in "~/"*)
> x="${HOME}/${x#"~/"}"
> esac
+ case "$x" in
+ x=/home/user/someDirectory
user@host:~$ echo $x
+ echo /home/user/someDirectory
/home/user/someDirectory
user@host:~$
This structure explicitly check the presence of a leading ~
and replaces it with the user home dir if it is found.
Following your comment, the x="${HOME}/${x#"~/"}"
may indeed be surprising for someone not used in shell programming, but is in fact linked to the same POSIX rule I quoted above.
As imposed by the POSIX standard, quote removal happens last and parameter expansion happens very early. Thus, ${#"~"}
is evaluated and expanded far before the evaluation of the outer quotes. In turns, as defined in Parameter expansion rules:
In each case that a value of word is needed (based on the state of
parameter, as described below), word shall be subjected to tilde
expansion, parameter expansion, command substitution, and arithmetic
expansion.
Thus, the right side of the #
operator must be properly quoted or escaped to avoid tilde expansion.
So, to state it differently, when the shell interpretor looks at x="${HOME}/${x#"~/"}"
, he sees:
${HOME}
and${x#"~/"}
must be expanded.
${HOME}
is expanded to the content of the$HOME
variable.
${x#"~/"}
triggers a nested expansion:"~/"
is parsed but, being quoted, is treated as a literal1. You could have used single quotes here with the same result.
${x#"~/"}
expression itself is now expanded, resulting in the prefix~/
being removed from the value of$x
.- The result of the above is now concatenated: the expansion of
${HOME}
, the literal/
, the expansion${x#"~/"}
. - The end-result is enclosed in double-quotes, functionally preventing word splitting. I say functionally here because these double quotes are not technically required (see here and there for instance), but as a personal style as soon as an assignments gets anything beyond
a=$b
I usually find it clearer add double-quotes.
By-the-way, if look more closely to the case
syntax, you will see the "~/"*
construction which relies on the same concept as x=~/'someDirectory'
I explained above (here again, double and simple quotes could be used interchangeably).
Don't worry if these things may seem obscure at the first sight (maybe even at the second or later sights!). In my opinion, parameter expansion are, with subshells, one of the most complex concept to grasp when programming in shell language.
I know that some people may vigorously disagree, but if you would-like to learn shell programming more in depth I encourage you to read the Advanced Bash Scripting Guide: it teaches Bash-scripting, so with a lot of extensions and bells-and-whistles compared to POSIX shell scripting, but I found it well written with loads of practical examples. Once you manage this, it is easy to restrict yourself to POSIX features when you need to, I personally think that entering directly in the POSIX realm is an unnecessary steep learning curve for beginners (compare my POSIX tilde replacement with @m0dular's regex-like Bash equivalent to get an idea of what I mean ;) !).
1: Which leads me into finding a bug in Dash which don't implement tilde expansion here correctly (verifiable using x='~/foo'; echo "${x#~/}"
). Parameter expansion is a complex field both for the user and the shell developers themselves!
How is the bash shell parsing the linex="${HOME}/${x#"~/"}"
? It looks like a concatenation of 3 strings:"${HOME}/${x#"
,~/
, and"}"
. Does the shell allow for nested double-quotes when the inner pair of double quotes is inside a${ }
block?
– Andrew
Oct 21 '17 at 2:35
@Andrew: I have complete my answer with additional information hopefully addressing your comment.
– WhiteWinterWolf
Oct 21 '17 at 8:41
Thanks, this is a great answer. I've learned a ton from reading it. Wish I could upvote it more than once:)
– Andrew
Oct 21 '17 at 14:03
@WhiteWinterWolf: still, shell does not see the nested quotes whatever the result is.
– avp
Nov 22 '18 at 10:15
add a comment |
The POSIX standard imposes word expansion to be done in the following order (emphasize is mine):
Tilde expansion (see Tilde Expansion), parameter expansion (see Parameter Expansion), command substitution (see Command Substitution),
and arithmetic expansion (see Arithmetic Expansion) shall be
performed, beginning to end. See item 5 in Token Recognition.
Field splitting (see Field Splitting) shall be performed on the portions of the fields generated by step 1, unless IFS is null.
Pathname expansion (see Pathname Expansion) shall be performed, unless set -f is in effect.
Quote removal (see Quote Removal) shall always be performed last.
The only point which interests us here is the first one: as you can see tilde expansion is processed before parameter expansion:
- The shell attempts a tilde expansion on
echo $x
, there is no tilde to be found, so it proceeds. - The shell attempts a parameter expansion on
echo $x
,$x
is found and expanded and the command-line becomesecho ~/someDirectory
. - Processing continues, tilde expansion having already been processed the
~
character remains as-is.
By using the quotes while assigning the $x
, you were explicitly requesting to not expand the tilde and treat it like a normal character. A thing often missed is that in shell commands you don't have to quote the whole string, so you can make the expansion happen right during the variable assignment:
user@host:~$ set -o xtrace
user@host:~$ x=~/'someDirectory'
+ x=/home/user/someDirectory
user@host:~$ echo $x
+ echo /home/user/someDirectory
/home/user/someDirectory
user@host:~$
And you can also make the expansion occur on the echo
command-line as long as it can happen before parameter expansion:
user@host:~$ x='someDirectory'
+ x=someDirectory
user@host:~$ echo ~/$x
+ echo /home/user/someDirectory
/home/user/someDirectory
user@host:~$
If for some reason you really need to affect the tilde to the $x
variable without expansion, and be able to expand it at the echo
command, you must proceed in two times to force two expansions of the $x
variable to occur:
user@host:~$ x='~/someDirectory'
+ x='~/someDirectory'
user@host:~$ echo "$( eval echo $x )"
++ eval echo '~/someDirectory'
+++ echo /home/user/someDirectory
+ echo /home/user/someDirectory
/home/user/someDirectory
user@host:~$
However, be aware that depending on the context where you use such structure it may have unwanted side-effect. As a rule of thumb, prefer to avoid using anything requiring eval
when you have another way.
If you want to specifically address the tilde issue as opposed to any other kind of expansion, such structure would be safer and portable:
user@host:~$ x='~/someDirectory'
+ x='~/someDirectory'
user@host:~$ case "$x" in "~/"*)
> x="${HOME}/${x#"~/"}"
> esac
+ case "$x" in
+ x=/home/user/someDirectory
user@host:~$ echo $x
+ echo /home/user/someDirectory
/home/user/someDirectory
user@host:~$
This structure explicitly check the presence of a leading ~
and replaces it with the user home dir if it is found.
Following your comment, the x="${HOME}/${x#"~/"}"
may indeed be surprising for someone not used in shell programming, but is in fact linked to the same POSIX rule I quoted above.
As imposed by the POSIX standard, quote removal happens last and parameter expansion happens very early. Thus, ${#"~"}
is evaluated and expanded far before the evaluation of the outer quotes. In turns, as defined in Parameter expansion rules:
In each case that a value of word is needed (based on the state of
parameter, as described below), word shall be subjected to tilde
expansion, parameter expansion, command substitution, and arithmetic
expansion.
Thus, the right side of the #
operator must be properly quoted or escaped to avoid tilde expansion.
So, to state it differently, when the shell interpretor looks at x="${HOME}/${x#"~/"}"
, he sees:
${HOME}
and${x#"~/"}
must be expanded.
${HOME}
is expanded to the content of the$HOME
variable.
${x#"~/"}
triggers a nested expansion:"~/"
is parsed but, being quoted, is treated as a literal1. You could have used single quotes here with the same result.
${x#"~/"}
expression itself is now expanded, resulting in the prefix~/
being removed from the value of$x
.- The result of the above is now concatenated: the expansion of
${HOME}
, the literal/
, the expansion${x#"~/"}
. - The end-result is enclosed in double-quotes, functionally preventing word splitting. I say functionally here because these double quotes are not technically required (see here and there for instance), but as a personal style as soon as an assignments gets anything beyond
a=$b
I usually find it clearer add double-quotes.
By-the-way, if look more closely to the case
syntax, you will see the "~/"*
construction which relies on the same concept as x=~/'someDirectory'
I explained above (here again, double and simple quotes could be used interchangeably).
Don't worry if these things may seem obscure at the first sight (maybe even at the second or later sights!). In my opinion, parameter expansion are, with subshells, one of the most complex concept to grasp when programming in shell language.
I know that some people may vigorously disagree, but if you would-like to learn shell programming more in depth I encourage you to read the Advanced Bash Scripting Guide: it teaches Bash-scripting, so with a lot of extensions and bells-and-whistles compared to POSIX shell scripting, but I found it well written with loads of practical examples. Once you manage this, it is easy to restrict yourself to POSIX features when you need to, I personally think that entering directly in the POSIX realm is an unnecessary steep learning curve for beginners (compare my POSIX tilde replacement with @m0dular's regex-like Bash equivalent to get an idea of what I mean ;) !).
1: Which leads me into finding a bug in Dash which don't implement tilde expansion here correctly (verifiable using x='~/foo'; echo "${x#~/}"
). Parameter expansion is a complex field both for the user and the shell developers themselves!
The POSIX standard imposes word expansion to be done in the following order (emphasize is mine):
Tilde expansion (see Tilde Expansion), parameter expansion (see Parameter Expansion), command substitution (see Command Substitution),
and arithmetic expansion (see Arithmetic Expansion) shall be
performed, beginning to end. See item 5 in Token Recognition.
Field splitting (see Field Splitting) shall be performed on the portions of the fields generated by step 1, unless IFS is null.
Pathname expansion (see Pathname Expansion) shall be performed, unless set -f is in effect.
Quote removal (see Quote Removal) shall always be performed last.
The only point which interests us here is the first one: as you can see tilde expansion is processed before parameter expansion:
- The shell attempts a tilde expansion on
echo $x
, there is no tilde to be found, so it proceeds. - The shell attempts a parameter expansion on
echo $x
,$x
is found and expanded and the command-line becomesecho ~/someDirectory
. - Processing continues, tilde expansion having already been processed the
~
character remains as-is.
By using the quotes while assigning the $x
, you were explicitly requesting to not expand the tilde and treat it like a normal character. A thing often missed is that in shell commands you don't have to quote the whole string, so you can make the expansion happen right during the variable assignment:
user@host:~$ set -o xtrace
user@host:~$ x=~/'someDirectory'
+ x=/home/user/someDirectory
user@host:~$ echo $x
+ echo /home/user/someDirectory
/home/user/someDirectory
user@host:~$
And you can also make the expansion occur on the echo
command-line as long as it can happen before parameter expansion:
user@host:~$ x='someDirectory'
+ x=someDirectory
user@host:~$ echo ~/$x
+ echo /home/user/someDirectory
/home/user/someDirectory
user@host:~$
If for some reason you really need to affect the tilde to the $x
variable without expansion, and be able to expand it at the echo
command, you must proceed in two times to force two expansions of the $x
variable to occur:
user@host:~$ x='~/someDirectory'
+ x='~/someDirectory'
user@host:~$ echo "$( eval echo $x )"
++ eval echo '~/someDirectory'
+++ echo /home/user/someDirectory
+ echo /home/user/someDirectory
/home/user/someDirectory
user@host:~$
However, be aware that depending on the context where you use such structure it may have unwanted side-effect. As a rule of thumb, prefer to avoid using anything requiring eval
when you have another way.
If you want to specifically address the tilde issue as opposed to any other kind of expansion, such structure would be safer and portable:
user@host:~$ x='~/someDirectory'
+ x='~/someDirectory'
user@host:~$ case "$x" in "~/"*)
> x="${HOME}/${x#"~/"}"
> esac
+ case "$x" in
+ x=/home/user/someDirectory
user@host:~$ echo $x
+ echo /home/user/someDirectory
/home/user/someDirectory
user@host:~$
This structure explicitly check the presence of a leading ~
and replaces it with the user home dir if it is found.
Following your comment, the x="${HOME}/${x#"~/"}"
may indeed be surprising for someone not used in shell programming, but is in fact linked to the same POSIX rule I quoted above.
As imposed by the POSIX standard, quote removal happens last and parameter expansion happens very early. Thus, ${#"~"}
is evaluated and expanded far before the evaluation of the outer quotes. In turns, as defined in Parameter expansion rules:
In each case that a value of word is needed (based on the state of
parameter, as described below), word shall be subjected to tilde
expansion, parameter expansion, command substitution, and arithmetic
expansion.
Thus, the right side of the #
operator must be properly quoted or escaped to avoid tilde expansion.
So, to state it differently, when the shell interpretor looks at x="${HOME}/${x#"~/"}"
, he sees:
${HOME}
and${x#"~/"}
must be expanded.
${HOME}
is expanded to the content of the$HOME
variable.
${x#"~/"}
triggers a nested expansion:"~/"
is parsed but, being quoted, is treated as a literal1. You could have used single quotes here with the same result.
${x#"~/"}
expression itself is now expanded, resulting in the prefix~/
being removed from the value of$x
.- The result of the above is now concatenated: the expansion of
${HOME}
, the literal/
, the expansion${x#"~/"}
. - The end-result is enclosed in double-quotes, functionally preventing word splitting. I say functionally here because these double quotes are not technically required (see here and there for instance), but as a personal style as soon as an assignments gets anything beyond
a=$b
I usually find it clearer add double-quotes.
By-the-way, if look more closely to the case
syntax, you will see the "~/"*
construction which relies on the same concept as x=~/'someDirectory'
I explained above (here again, double and simple quotes could be used interchangeably).
Don't worry if these things may seem obscure at the first sight (maybe even at the second or later sights!). In my opinion, parameter expansion are, with subshells, one of the most complex concept to grasp when programming in shell language.
I know that some people may vigorously disagree, but if you would-like to learn shell programming more in depth I encourage you to read the Advanced Bash Scripting Guide: it teaches Bash-scripting, so with a lot of extensions and bells-and-whistles compared to POSIX shell scripting, but I found it well written with loads of practical examples. Once you manage this, it is easy to restrict yourself to POSIX features when you need to, I personally think that entering directly in the POSIX realm is an unnecessary steep learning curve for beginners (compare my POSIX tilde replacement with @m0dular's regex-like Bash equivalent to get an idea of what I mean ;) !).
1: Which leads me into finding a bug in Dash which don't implement tilde expansion here correctly (verifiable using x='~/foo'; echo "${x#~/}"
). Parameter expansion is a complex field both for the user and the shell developers themselves!
edited Oct 21 '17 at 8:40
answered Oct 20 '17 at 21:33
WhiteWinterWolfWhiteWinterWolf
1,74610 silver badges31 bronze badges
1,74610 silver badges31 bronze badges
How is the bash shell parsing the linex="${HOME}/${x#"~/"}"
? It looks like a concatenation of 3 strings:"${HOME}/${x#"
,~/
, and"}"
. Does the shell allow for nested double-quotes when the inner pair of double quotes is inside a${ }
block?
– Andrew
Oct 21 '17 at 2:35
@Andrew: I have complete my answer with additional information hopefully addressing your comment.
– WhiteWinterWolf
Oct 21 '17 at 8:41
Thanks, this is a great answer. I've learned a ton from reading it. Wish I could upvote it more than once:)
– Andrew
Oct 21 '17 at 14:03
@WhiteWinterWolf: still, shell does not see the nested quotes whatever the result is.
– avp
Nov 22 '18 at 10:15
add a comment |
How is the bash shell parsing the linex="${HOME}/${x#"~/"}"
? It looks like a concatenation of 3 strings:"${HOME}/${x#"
,~/
, and"}"
. Does the shell allow for nested double-quotes when the inner pair of double quotes is inside a${ }
block?
– Andrew
Oct 21 '17 at 2:35
@Andrew: I have complete my answer with additional information hopefully addressing your comment.
– WhiteWinterWolf
Oct 21 '17 at 8:41
Thanks, this is a great answer. I've learned a ton from reading it. Wish I could upvote it more than once:)
– Andrew
Oct 21 '17 at 14:03
@WhiteWinterWolf: still, shell does not see the nested quotes whatever the result is.
– avp
Nov 22 '18 at 10:15
How is the bash shell parsing the line
x="${HOME}/${x#"~/"}"
? It looks like a concatenation of 3 strings: "${HOME}/${x#"
, ~/
, and "}"
. Does the shell allow for nested double-quotes when the inner pair of double quotes is inside a ${ }
block?– Andrew
Oct 21 '17 at 2:35
How is the bash shell parsing the line
x="${HOME}/${x#"~/"}"
? It looks like a concatenation of 3 strings: "${HOME}/${x#"
, ~/
, and "}"
. Does the shell allow for nested double-quotes when the inner pair of double quotes is inside a ${ }
block?– Andrew
Oct 21 '17 at 2:35
@Andrew: I have complete my answer with additional information hopefully addressing your comment.
– WhiteWinterWolf
Oct 21 '17 at 8:41
@Andrew: I have complete my answer with additional information hopefully addressing your comment.
– WhiteWinterWolf
Oct 21 '17 at 8:41
Thanks, this is a great answer. I've learned a ton from reading it. Wish I could upvote it more than once:)
– Andrew
Oct 21 '17 at 14:03
Thanks, this is a great answer. I've learned a ton from reading it. Wish I could upvote it more than once:)
– Andrew
Oct 21 '17 at 14:03
@WhiteWinterWolf: still, shell does not see the nested quotes whatever the result is.
– avp
Nov 22 '18 at 10:15
@WhiteWinterWolf: still, shell does not see the nested quotes whatever the result is.
– avp
Nov 22 '18 at 10:15
add a comment |
One possible answer:
eval echo "$x"
Since you're reading input from a file, I would not do this.
You could search and replace the ~ with the value of $HOME, like this:
x='~/.config'
x="${x//~/$HOME}"
echo "$x"
Gives me:
/home/adrian/.config
Note that the${parameter/pattern/string}
expansion is a Bash extension and may not be available in other shells.
– WhiteWinterWolf
Oct 20 '17 at 21:53
True. The OP did mention he was using Bash, so I think it's an appropriate answer.
– m0dular
Oct 20 '17 at 22:06
I agree, as long as one is sticking to Bash why not fully take advantage of it (not everybody need portability everywhere), but it's just worth to note it for non-Bash users (several distro now ship with Dash instead of Bash for instance) so affected users are not surprised.
– WhiteWinterWolf
Oct 20 '17 at 22:13
I took the liberty to mention your post in my digression about differences between Bash extensions and POSIX shell scripting, as I think that your Bash single-line regex-like statement compared to my POSIXcase
structure illustrate well how Bash scripting is more user-friendly specially for beginners.
– WhiteWinterWolf
Oct 21 '17 at 8:43
add a comment |
One possible answer:
eval echo "$x"
Since you're reading input from a file, I would not do this.
You could search and replace the ~ with the value of $HOME, like this:
x='~/.config'
x="${x//~/$HOME}"
echo "$x"
Gives me:
/home/adrian/.config
Note that the${parameter/pattern/string}
expansion is a Bash extension and may not be available in other shells.
– WhiteWinterWolf
Oct 20 '17 at 21:53
True. The OP did mention he was using Bash, so I think it's an appropriate answer.
– m0dular
Oct 20 '17 at 22:06
I agree, as long as one is sticking to Bash why not fully take advantage of it (not everybody need portability everywhere), but it's just worth to note it for non-Bash users (several distro now ship with Dash instead of Bash for instance) so affected users are not surprised.
– WhiteWinterWolf
Oct 20 '17 at 22:13
I took the liberty to mention your post in my digression about differences between Bash extensions and POSIX shell scripting, as I think that your Bash single-line regex-like statement compared to my POSIXcase
structure illustrate well how Bash scripting is more user-friendly specially for beginners.
– WhiteWinterWolf
Oct 21 '17 at 8:43
add a comment |
One possible answer:
eval echo "$x"
Since you're reading input from a file, I would not do this.
You could search and replace the ~ with the value of $HOME, like this:
x='~/.config'
x="${x//~/$HOME}"
echo "$x"
Gives me:
/home/adrian/.config
One possible answer:
eval echo "$x"
Since you're reading input from a file, I would not do this.
You could search and replace the ~ with the value of $HOME, like this:
x='~/.config'
x="${x//~/$HOME}"
echo "$x"
Gives me:
/home/adrian/.config
answered Oct 20 '17 at 21:38
m0dularm0dular
8462 silver badges6 bronze badges
8462 silver badges6 bronze badges
Note that the${parameter/pattern/string}
expansion is a Bash extension and may not be available in other shells.
– WhiteWinterWolf
Oct 20 '17 at 21:53
True. The OP did mention he was using Bash, so I think it's an appropriate answer.
– m0dular
Oct 20 '17 at 22:06
I agree, as long as one is sticking to Bash why not fully take advantage of it (not everybody need portability everywhere), but it's just worth to note it for non-Bash users (several distro now ship with Dash instead of Bash for instance) so affected users are not surprised.
– WhiteWinterWolf
Oct 20 '17 at 22:13
I took the liberty to mention your post in my digression about differences between Bash extensions and POSIX shell scripting, as I think that your Bash single-line regex-like statement compared to my POSIXcase
structure illustrate well how Bash scripting is more user-friendly specially for beginners.
– WhiteWinterWolf
Oct 21 '17 at 8:43
add a comment |
Note that the${parameter/pattern/string}
expansion is a Bash extension and may not be available in other shells.
– WhiteWinterWolf
Oct 20 '17 at 21:53
True. The OP did mention he was using Bash, so I think it's an appropriate answer.
– m0dular
Oct 20 '17 at 22:06
I agree, as long as one is sticking to Bash why not fully take advantage of it (not everybody need portability everywhere), but it's just worth to note it for non-Bash users (several distro now ship with Dash instead of Bash for instance) so affected users are not surprised.
– WhiteWinterWolf
Oct 20 '17 at 22:13
I took the liberty to mention your post in my digression about differences between Bash extensions and POSIX shell scripting, as I think that your Bash single-line regex-like statement compared to my POSIXcase
structure illustrate well how Bash scripting is more user-friendly specially for beginners.
– WhiteWinterWolf
Oct 21 '17 at 8:43
Note that the
${parameter/pattern/string}
expansion is a Bash extension and may not be available in other shells.– WhiteWinterWolf
Oct 20 '17 at 21:53
Note that the
${parameter/pattern/string}
expansion is a Bash extension and may not be available in other shells.– WhiteWinterWolf
Oct 20 '17 at 21:53
True. The OP did mention he was using Bash, so I think it's an appropriate answer.
– m0dular
Oct 20 '17 at 22:06
True. The OP did mention he was using Bash, so I think it's an appropriate answer.
– m0dular
Oct 20 '17 at 22:06
I agree, as long as one is sticking to Bash why not fully take advantage of it (not everybody need portability everywhere), but it's just worth to note it for non-Bash users (several distro now ship with Dash instead of Bash for instance) so affected users are not surprised.
– WhiteWinterWolf
Oct 20 '17 at 22:13
I agree, as long as one is sticking to Bash why not fully take advantage of it (not everybody need portability everywhere), but it's just worth to note it for non-Bash users (several distro now ship with Dash instead of Bash for instance) so affected users are not surprised.
– WhiteWinterWolf
Oct 20 '17 at 22:13
I took the liberty to mention your post in my digression about differences between Bash extensions and POSIX shell scripting, as I think that your Bash single-line regex-like statement compared to my POSIX
case
structure illustrate well how Bash scripting is more user-friendly specially for beginners.– WhiteWinterWolf
Oct 21 '17 at 8:43
I took the liberty to mention your post in my digression about differences between Bash extensions and POSIX shell scripting, as I think that your Bash single-line regex-like statement compared to my POSIX
case
structure illustrate well how Bash scripting is more user-friendly specially for beginners.– WhiteWinterWolf
Oct 21 '17 at 8:43
add a comment |
Thanks for contributing an answer to Unix & Linux Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f399407%2fhow-can-i-expand-a-tilde-as-part-of-a-variable%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
In ZSH this is
x='~'; print -l ${x} ${~x}
. I gave up after digging through thebash
manual for a while.– thrig
Oct 20 '17 at 19:02
@thrig: This is not a bashism, this behavior is POSIX.
– WhiteWinterWolf
Oct 20 '17 at 21:35
Extremely closely related (if not a dupe): unix.stackexchange.com/questions/151850/…
– Kusalananda♦
Oct 20 '17 at 21:42
@Kusalananda: I'm not sure this is a dupe as the reason here is somewhat different: the OP did not enclose $x between quotes when echoing it.
– WhiteWinterWolf
Oct 20 '17 at 21:55
You don't put tildes in the input file. Problem solved.
– chepner
Oct 21 '17 at 1:24