What's the different between with a ~ and without a ~ in a string variable in Bash?

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP











up vote
2
down vote

favorite












I'm using a dotfile manage software, named dotdrop. Using a config file named .env, contents like: git_folder="~/code/Git".



Also use a script to setup this dotfile tool before the first use of it, as follows,



#!/bin/bash

env1="~/Dropbox/.env"
env2="/mnt/d/Dropbox/.env"

if [ -f $env1 ]; then
echo "Found dotdrop env file, installing dotfiles..."
source $env1
eval $(grep -v "^#" $env1) dotdrop --cfg=$git_folder/dotfiles/config.yaml install
elif [ -f $env2 ]; then
echo "Found dotdrop env file, installing dotfiles..."
source $env2
eval $(grep -v "^#" $env2) dotdrop --cfg=$git_folder/dotfiles/config.yaml install
else echo "Pls sync environment files first!"
fi


If I store my config file at ~/Dropbox/.env, when I run the script, I just got "Pls sync environment files first!"(run in if condition is expected). If config file stored at /mnt/d/Dropbox/.env, the script will go through the elif condition, which is expected.



Find the reason until I run the script in dubug mode, and get the difference:



➜ scripts git:(master) ✗ bash -x dotdrop_setup.sh 
+ env1='~/Dropbox/.env'
+ env2=/mnt/d/Dropbox/.env
+ '[' -f '~/Dropbox/.env' ']'
+ '[' -f /mnt/d/Dropbox/.env ']'
+ echo 'Pls sync environment files first!'
Pls sync environment files first!


So, I think the difference between ~ and /home/user is the reason.



After I change ~ to /home/roach(roach is user name), it works.



➜ scripts git:(master) ✗ bash -x dotdrop_setup.sh
+ env1=/home/roach/Dropbox/.env
+ env2=/mnt/d/Dropbox/.env
+ '[' -f /home/roach/Dropbox/.env ']'
+ echo 'Found dotdrop env file, installing dotfiles...'
Found dotdrop env file, installing dotfiles...
+ source /home/roach/Dropbox/.env
++ git_folder='~/code/Git'
++ grep -v '^#' /home/roach/Dropbox/.env
+ eval git_folder='~/code/Git'
++ dotdrop '--cfg=~/code/Git/dotfiles/config.yaml' install
_ _ _
__| | ___ | |_ __| |_ __ ___ _ __
/ _` |/ _ | __/ _` | '__/ _ | '_ |
__,_|___/ ____,_|_| ___/| .__/ v0.22.0
|_|


0 dotfile(s) installed.


The debug shows '' surround + env1='~/Dropbox/.env' is removed which I think is the reason.



But, WHY?




Additional question,



alias dotdrop="eval $(grep -v "^#" $env1) /usr/bin/dotdrop --cfg=$git_folder/dotfiles/config.yaml install" is a config add to bashrc, zshrc, etc. It doesn't work if I add it to my script directly!



Finally, found I have to add source $env,



So WHY it works in a bashrc file?










share|improve this question























  • Are you running this script with some other user then user you mentioned in question?
    – Debian_yadav
    1 hour ago











  • Hi, @Debian_yadav. I run with same user not sure for your meaning, so I updated some detail about this question.
    – roachsinai
    1 hour ago














up vote
2
down vote

favorite












I'm using a dotfile manage software, named dotdrop. Using a config file named .env, contents like: git_folder="~/code/Git".



Also use a script to setup this dotfile tool before the first use of it, as follows,



#!/bin/bash

env1="~/Dropbox/.env"
env2="/mnt/d/Dropbox/.env"

if [ -f $env1 ]; then
echo "Found dotdrop env file, installing dotfiles..."
source $env1
eval $(grep -v "^#" $env1) dotdrop --cfg=$git_folder/dotfiles/config.yaml install
elif [ -f $env2 ]; then
echo "Found dotdrop env file, installing dotfiles..."
source $env2
eval $(grep -v "^#" $env2) dotdrop --cfg=$git_folder/dotfiles/config.yaml install
else echo "Pls sync environment files first!"
fi


If I store my config file at ~/Dropbox/.env, when I run the script, I just got "Pls sync environment files first!"(run in if condition is expected). If config file stored at /mnt/d/Dropbox/.env, the script will go through the elif condition, which is expected.



Find the reason until I run the script in dubug mode, and get the difference:



➜ scripts git:(master) ✗ bash -x dotdrop_setup.sh 
+ env1='~/Dropbox/.env'
+ env2=/mnt/d/Dropbox/.env
+ '[' -f '~/Dropbox/.env' ']'
+ '[' -f /mnt/d/Dropbox/.env ']'
+ echo 'Pls sync environment files first!'
Pls sync environment files first!


So, I think the difference between ~ and /home/user is the reason.



After I change ~ to /home/roach(roach is user name), it works.



➜ scripts git:(master) ✗ bash -x dotdrop_setup.sh
+ env1=/home/roach/Dropbox/.env
+ env2=/mnt/d/Dropbox/.env
+ '[' -f /home/roach/Dropbox/.env ']'
+ echo 'Found dotdrop env file, installing dotfiles...'
Found dotdrop env file, installing dotfiles...
+ source /home/roach/Dropbox/.env
++ git_folder='~/code/Git'
++ grep -v '^#' /home/roach/Dropbox/.env
+ eval git_folder='~/code/Git'
++ dotdrop '--cfg=~/code/Git/dotfiles/config.yaml' install
_ _ _
__| | ___ | |_ __| |_ __ ___ _ __
/ _` |/ _ | __/ _` | '__/ _ | '_ |
__,_|___/ ____,_|_| ___/| .__/ v0.22.0
|_|


0 dotfile(s) installed.


The debug shows '' surround + env1='~/Dropbox/.env' is removed which I think is the reason.



But, WHY?




Additional question,



alias dotdrop="eval $(grep -v "^#" $env1) /usr/bin/dotdrop --cfg=$git_folder/dotfiles/config.yaml install" is a config add to bashrc, zshrc, etc. It doesn't work if I add it to my script directly!



Finally, found I have to add source $env,



So WHY it works in a bashrc file?










share|improve this question























  • Are you running this script with some other user then user you mentioned in question?
    – Debian_yadav
    1 hour ago











  • Hi, @Debian_yadav. I run with same user not sure for your meaning, so I updated some detail about this question.
    – roachsinai
    1 hour ago












up vote
2
down vote

favorite









up vote
2
down vote

favorite











I'm using a dotfile manage software, named dotdrop. Using a config file named .env, contents like: git_folder="~/code/Git".



Also use a script to setup this dotfile tool before the first use of it, as follows,



#!/bin/bash

env1="~/Dropbox/.env"
env2="/mnt/d/Dropbox/.env"

if [ -f $env1 ]; then
echo "Found dotdrop env file, installing dotfiles..."
source $env1
eval $(grep -v "^#" $env1) dotdrop --cfg=$git_folder/dotfiles/config.yaml install
elif [ -f $env2 ]; then
echo "Found dotdrop env file, installing dotfiles..."
source $env2
eval $(grep -v "^#" $env2) dotdrop --cfg=$git_folder/dotfiles/config.yaml install
else echo "Pls sync environment files first!"
fi


If I store my config file at ~/Dropbox/.env, when I run the script, I just got "Pls sync environment files first!"(run in if condition is expected). If config file stored at /mnt/d/Dropbox/.env, the script will go through the elif condition, which is expected.



Find the reason until I run the script in dubug mode, and get the difference:



➜ scripts git:(master) ✗ bash -x dotdrop_setup.sh 
+ env1='~/Dropbox/.env'
+ env2=/mnt/d/Dropbox/.env
+ '[' -f '~/Dropbox/.env' ']'
+ '[' -f /mnt/d/Dropbox/.env ']'
+ echo 'Pls sync environment files first!'
Pls sync environment files first!


So, I think the difference between ~ and /home/user is the reason.



After I change ~ to /home/roach(roach is user name), it works.



➜ scripts git:(master) ✗ bash -x dotdrop_setup.sh
+ env1=/home/roach/Dropbox/.env
+ env2=/mnt/d/Dropbox/.env
+ '[' -f /home/roach/Dropbox/.env ']'
+ echo 'Found dotdrop env file, installing dotfiles...'
Found dotdrop env file, installing dotfiles...
+ source /home/roach/Dropbox/.env
++ git_folder='~/code/Git'
++ grep -v '^#' /home/roach/Dropbox/.env
+ eval git_folder='~/code/Git'
++ dotdrop '--cfg=~/code/Git/dotfiles/config.yaml' install
_ _ _
__| | ___ | |_ __| |_ __ ___ _ __
/ _` |/ _ | __/ _` | '__/ _ | '_ |
__,_|___/ ____,_|_| ___/| .__/ v0.22.0
|_|


0 dotfile(s) installed.


The debug shows '' surround + env1='~/Dropbox/.env' is removed which I think is the reason.



But, WHY?




Additional question,



alias dotdrop="eval $(grep -v "^#" $env1) /usr/bin/dotdrop --cfg=$git_folder/dotfiles/config.yaml install" is a config add to bashrc, zshrc, etc. It doesn't work if I add it to my script directly!



Finally, found I have to add source $env,



So WHY it works in a bashrc file?










share|improve this question















I'm using a dotfile manage software, named dotdrop. Using a config file named .env, contents like: git_folder="~/code/Git".



Also use a script to setup this dotfile tool before the first use of it, as follows,



#!/bin/bash

env1="~/Dropbox/.env"
env2="/mnt/d/Dropbox/.env"

if [ -f $env1 ]; then
echo "Found dotdrop env file, installing dotfiles..."
source $env1
eval $(grep -v "^#" $env1) dotdrop --cfg=$git_folder/dotfiles/config.yaml install
elif [ -f $env2 ]; then
echo "Found dotdrop env file, installing dotfiles..."
source $env2
eval $(grep -v "^#" $env2) dotdrop --cfg=$git_folder/dotfiles/config.yaml install
else echo "Pls sync environment files first!"
fi


If I store my config file at ~/Dropbox/.env, when I run the script, I just got "Pls sync environment files first!"(run in if condition is expected). If config file stored at /mnt/d/Dropbox/.env, the script will go through the elif condition, which is expected.



Find the reason until I run the script in dubug mode, and get the difference:



➜ scripts git:(master) ✗ bash -x dotdrop_setup.sh 
+ env1='~/Dropbox/.env'
+ env2=/mnt/d/Dropbox/.env
+ '[' -f '~/Dropbox/.env' ']'
+ '[' -f /mnt/d/Dropbox/.env ']'
+ echo 'Pls sync environment files first!'
Pls sync environment files first!


So, I think the difference between ~ and /home/user is the reason.



After I change ~ to /home/roach(roach is user name), it works.



➜ scripts git:(master) ✗ bash -x dotdrop_setup.sh
+ env1=/home/roach/Dropbox/.env
+ env2=/mnt/d/Dropbox/.env
+ '[' -f /home/roach/Dropbox/.env ']'
+ echo 'Found dotdrop env file, installing dotfiles...'
Found dotdrop env file, installing dotfiles...
+ source /home/roach/Dropbox/.env
++ git_folder='~/code/Git'
++ grep -v '^#' /home/roach/Dropbox/.env
+ eval git_folder='~/code/Git'
++ dotdrop '--cfg=~/code/Git/dotfiles/config.yaml' install
_ _ _
__| | ___ | |_ __| |_ __ ___ _ __
/ _` |/ _ | __/ _` | '__/ _ | '_ |
__,_|___/ ____,_|_| ___/| .__/ v0.22.0
|_|


0 dotfile(s) installed.


The debug shows '' surround + env1='~/Dropbox/.env' is removed which I think is the reason.



But, WHY?




Additional question,



alias dotdrop="eval $(grep -v "^#" $env1) /usr/bin/dotdrop --cfg=$git_folder/dotfiles/config.yaml install" is a config add to bashrc, zshrc, etc. It doesn't work if I add it to my script directly!



Finally, found I have to add source $env,



So WHY it works in a bashrc file?







bash shell quoting home tilde






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited 41 mins ago

























asked 1 hour ago









roachsinai

457




457











  • Are you running this script with some other user then user you mentioned in question?
    – Debian_yadav
    1 hour ago











  • Hi, @Debian_yadav. I run with same user not sure for your meaning, so I updated some detail about this question.
    – roachsinai
    1 hour ago
















  • Are you running this script with some other user then user you mentioned in question?
    – Debian_yadav
    1 hour ago











  • Hi, @Debian_yadav. I run with same user not sure for your meaning, so I updated some detail about this question.
    – roachsinai
    1 hour ago















Are you running this script with some other user then user you mentioned in question?
– Debian_yadav
1 hour ago





Are you running this script with some other user then user you mentioned in question?
– Debian_yadav
1 hour ago













Hi, @Debian_yadav. I run with same user not sure for your meaning, so I updated some detail about this question.
– roachsinai
1 hour ago




Hi, @Debian_yadav. I run with same user not sure for your meaning, so I updated some detail about this question.
– roachsinai
1 hour ago










1 Answer
1






active

oldest

votes

















up vote
3
down vote



accepted










~ is a shortcut for your home directory, but only when it appears at the beginning of a string outside quotes. The beginning of the right-hand side of an assignment operator is the beginning of a string, so env1=~/Dropbox/.env would work (or env1=~"/Dropbox/.env" or any number of variations). It sets env1 to /home/roach/Dropbox/.env. But env1="~/Dropbox/.env" sets env1 to the exact string ~/Dropbox/.env, which as a file name looks inside a directory with the one-character name ~ in the current directory.



Tilde is an abbreviation, not a wildcard. $env1 outside quotes expands wildcards in the value of env1, but it doesn't expand the tilde because the tilde is not a wildcard.



You can also use env1="$HOME/Dropbox/.env". This is equivalent to env1=~/Dropbox/.env. The character $ (dollar) has a special meaning inside double quotes (it's the same meaning as outside quotes): it starts a variable substitution (or a command or arithmetic substitution). The character ~ (tilde), on the other hand, is just an ordinary character when it's inside quotes, even double quotes.




As for the alias, the reason it doesn't work in a bash script is that bash doesn't expand aliases in scripts by default. It won't work in any script unless you include or source the definition of the alias in that script, since aliases are a property of each shell instance. They aren't part of a process's environment.



The reason the alias works at all in your second script is that dotdrop itself expands the tilde when it reads its configuration value.






share|improve this answer




















  • thanks for your answer!
    – roachsinai
    40 mins ago










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',
convertImagesToLinks: false,
noModals: false,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);



);













 

draft saved


draft discarded


















StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f476959%2fwhats-the-different-between-with-a-and-without-a-in-a-string-variable-in-ba%23new-answer', 'question_page');

);

Post as a guest






























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes








up vote
3
down vote



accepted










~ is a shortcut for your home directory, but only when it appears at the beginning of a string outside quotes. The beginning of the right-hand side of an assignment operator is the beginning of a string, so env1=~/Dropbox/.env would work (or env1=~"/Dropbox/.env" or any number of variations). It sets env1 to /home/roach/Dropbox/.env. But env1="~/Dropbox/.env" sets env1 to the exact string ~/Dropbox/.env, which as a file name looks inside a directory with the one-character name ~ in the current directory.



Tilde is an abbreviation, not a wildcard. $env1 outside quotes expands wildcards in the value of env1, but it doesn't expand the tilde because the tilde is not a wildcard.



You can also use env1="$HOME/Dropbox/.env". This is equivalent to env1=~/Dropbox/.env. The character $ (dollar) has a special meaning inside double quotes (it's the same meaning as outside quotes): it starts a variable substitution (or a command or arithmetic substitution). The character ~ (tilde), on the other hand, is just an ordinary character when it's inside quotes, even double quotes.




As for the alias, the reason it doesn't work in a bash script is that bash doesn't expand aliases in scripts by default. It won't work in any script unless you include or source the definition of the alias in that script, since aliases are a property of each shell instance. They aren't part of a process's environment.



The reason the alias works at all in your second script is that dotdrop itself expands the tilde when it reads its configuration value.






share|improve this answer




















  • thanks for your answer!
    – roachsinai
    40 mins ago














up vote
3
down vote



accepted










~ is a shortcut for your home directory, but only when it appears at the beginning of a string outside quotes. The beginning of the right-hand side of an assignment operator is the beginning of a string, so env1=~/Dropbox/.env would work (or env1=~"/Dropbox/.env" or any number of variations). It sets env1 to /home/roach/Dropbox/.env. But env1="~/Dropbox/.env" sets env1 to the exact string ~/Dropbox/.env, which as a file name looks inside a directory with the one-character name ~ in the current directory.



Tilde is an abbreviation, not a wildcard. $env1 outside quotes expands wildcards in the value of env1, but it doesn't expand the tilde because the tilde is not a wildcard.



You can also use env1="$HOME/Dropbox/.env". This is equivalent to env1=~/Dropbox/.env. The character $ (dollar) has a special meaning inside double quotes (it's the same meaning as outside quotes): it starts a variable substitution (or a command or arithmetic substitution). The character ~ (tilde), on the other hand, is just an ordinary character when it's inside quotes, even double quotes.




As for the alias, the reason it doesn't work in a bash script is that bash doesn't expand aliases in scripts by default. It won't work in any script unless you include or source the definition of the alias in that script, since aliases are a property of each shell instance. They aren't part of a process's environment.



The reason the alias works at all in your second script is that dotdrop itself expands the tilde when it reads its configuration value.






share|improve this answer




















  • thanks for your answer!
    – roachsinai
    40 mins ago












up vote
3
down vote



accepted







up vote
3
down vote



accepted






~ is a shortcut for your home directory, but only when it appears at the beginning of a string outside quotes. The beginning of the right-hand side of an assignment operator is the beginning of a string, so env1=~/Dropbox/.env would work (or env1=~"/Dropbox/.env" or any number of variations). It sets env1 to /home/roach/Dropbox/.env. But env1="~/Dropbox/.env" sets env1 to the exact string ~/Dropbox/.env, which as a file name looks inside a directory with the one-character name ~ in the current directory.



Tilde is an abbreviation, not a wildcard. $env1 outside quotes expands wildcards in the value of env1, but it doesn't expand the tilde because the tilde is not a wildcard.



You can also use env1="$HOME/Dropbox/.env". This is equivalent to env1=~/Dropbox/.env. The character $ (dollar) has a special meaning inside double quotes (it's the same meaning as outside quotes): it starts a variable substitution (or a command or arithmetic substitution). The character ~ (tilde), on the other hand, is just an ordinary character when it's inside quotes, even double quotes.




As for the alias, the reason it doesn't work in a bash script is that bash doesn't expand aliases in scripts by default. It won't work in any script unless you include or source the definition of the alias in that script, since aliases are a property of each shell instance. They aren't part of a process's environment.



The reason the alias works at all in your second script is that dotdrop itself expands the tilde when it reads its configuration value.






share|improve this answer












~ is a shortcut for your home directory, but only when it appears at the beginning of a string outside quotes. The beginning of the right-hand side of an assignment operator is the beginning of a string, so env1=~/Dropbox/.env would work (or env1=~"/Dropbox/.env" or any number of variations). It sets env1 to /home/roach/Dropbox/.env. But env1="~/Dropbox/.env" sets env1 to the exact string ~/Dropbox/.env, which as a file name looks inside a directory with the one-character name ~ in the current directory.



Tilde is an abbreviation, not a wildcard. $env1 outside quotes expands wildcards in the value of env1, but it doesn't expand the tilde because the tilde is not a wildcard.



You can also use env1="$HOME/Dropbox/.env". This is equivalent to env1=~/Dropbox/.env. The character $ (dollar) has a special meaning inside double quotes (it's the same meaning as outside quotes): it starts a variable substitution (or a command or arithmetic substitution). The character ~ (tilde), on the other hand, is just an ordinary character when it's inside quotes, even double quotes.




As for the alias, the reason it doesn't work in a bash script is that bash doesn't expand aliases in scripts by default. It won't work in any script unless you include or source the definition of the alias in that script, since aliases are a property of each shell instance. They aren't part of a process's environment.



The reason the alias works at all in your second script is that dotdrop itself expands the tilde when it reads its configuration value.







share|improve this answer












share|improve this answer



share|improve this answer










answered 53 mins ago









Gilles

515k12210251554




515k12210251554











  • thanks for your answer!
    – roachsinai
    40 mins ago
















  • thanks for your answer!
    – roachsinai
    40 mins ago















thanks for your answer!
– roachsinai
40 mins ago




thanks for your answer!
– roachsinai
40 mins ago

















 

draft saved


draft discarded















































 


draft saved


draft discarded














StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f476959%2fwhats-the-different-between-with-a-and-without-a-in-a-string-variable-in-ba%23new-answer', 'question_page');

);

Post as a guest













































































Comments

Popular posts from this blog

What does second last employer means? [closed]

List of Gilmore Girls characters

Confectionery