how do I escape spaces in $HOME in a bash script? - macos

I'm trying to run a script which uses my $HOME variable to set things up (it's gitolite, by the way).
However, it's failing because I'm on a system where the home directory path has spaces in it.
I want to hack the gitolite bash script at a single point so $HOME turns into something it can work with -- it gets used several times in the script and beyond, and in some places is concatenated to form subfolders, so wrapping it in "" won't work.
So to clean it up I need to say something like:
$HOME=(magic here)$HOME
(This is of course assuming that the perl scripts that come later don't also read the $HOME variable direct and also need fixing...)

Use quotes everywhere.
HOME="/Users/Foo Bar"
WORKDIR="$HOME"/Work
PLAYDIR="$HOME"/Games
MARATHONDIR="$PLAYDIR"/Marathon

Try this:
export HOME=`echo $HOME | sed -e "s/ /\\ /g"`
Hope that works for you!

Related

Why bash script does not run well?

I write a code in Bash script and the Linux does not run it correctly and printed character instead of character’s value.
Can anyone help me?
Aside from the confusion between backtick and ', you are also over-using the sub-shell syntax. You do not need to use echo $(cat $LOOP). You can just run cat $LOOP directly.
#!/bin/bash
for FILE in $(ls); do
echo "Here is ${file}:"
cat ${FILE}
echo ""
done
A couple of points of style as well:
Name your variables after the thing they represent. The loop is iterating over files in the current directory, so the name FILE is more descriptive than LOOP.
It is a good idea to get in the habit of enclosing your variable references in ${ ... } instead of just prefixing them with $. In simple scripts like this, it does not make a difference, but when your scripts get more complicated, you can get into trouble when you do not clearly delineate variable names.

.bashrc command to copy current working directory

I am trying to write an alias for the following command that takes your current working directory, surrounded by quotes, and copies it to the clipboard.
echo \"$(pwd)\" | xclip
However, writing an alias for this in .bashrc is not working quite right. This is the alias I have written:
alias cpwd="echo \"\$(pwd)\" | xclip"
But when that command is ran the double quotes are omitted. I have checked answers to similar problems, such as bash alias command with both single and double quotes, but I think I am escaping all the required characters, so I do not know why this command isn't working.
The current result of the command would be something like: home/user/My Folder rather than "home/user/My Folder" like I am wanting.
You need more escaping. You've correctly escaped the $; you need to do the same with the existing backslashes.
alias cpwd="echo \\"\$(pwd)\\" | xclip"
Alternatively, you can avoid all the escaping by using single quotes.
alias cpwd='echo \"$(pwd)\" | xclip'
Best of all, use a function instead of an alias. A function lets you write the command exactly as you would normally without any extra quotes or escaping.
cpwd() {
echo \"$(pwd)\" | xclip
}

How can I use source with variables?

I have tried multiple ways to get this to work, but no go: I just want to use $path in my source command.
#!/bin/bash
path="~/root/config/bash/"
source ~/root/config/bash/_private.sh
source ~/root/config/bash/config.sh
Tilde (~) will be treated literally in a path when put inside quotes, in a variable declaration, so source $path won't work.
You can:
Use eval (be careful):
source "$(eval echo $path)"
Or use alphabetic full path:
path=/home/user/root/config/bash/
Or if the user is same as the login user, use $HOME:
path="$HOME"/root/config/bash/
Or keep ~ outside of quotes
path=~/"root/config/bash/"
source "$path"
Bash parameters are expanded by the shell, before the command sees them as arguments.
source "$path" is all you need.
Unless you're talking about using it as a prefix, in which case, you could do:
source "${path}/_private.sh", etc.
However, if you're talking about using $path as if it were $PATH, and let it look for files there if they can't be found elsewhere, that would require custom logic.

Use `pbcopy` as path for cd command

I am using Automator on my Mac to set up a service that passes a selected folder to a bash shell script as arguments.
In the script I do:
for f in "$#"; do
printf "%q\n" "$f" | pbcopy
done
if I then do:
echo `pbpaste`
I get the path to my selected folder with spaces escaped (\). I then wanted to use this path to cd into that directory and do a bunch of other stuff (creating a blank directory structure). I hoped I could just do:
cd `pbpaste`
but this doesn't work.
If I type the path manually the cd works so I assume the is some issue with data types or returns or something??
I'll admit I don't really know what this script actually doing and may be going about this all wrong but but if anyone can explain what's going on here and how to get it working it that would be great but even better would be a pointer to a really good resource for a complete beginner to start learning about shell scripting.
I really like the idea of getting into this a bit more but all the resources I have found are either total basics (cd, ls, pwd etc) or really high level and assume a bunch of previous knowledge.
What I'd really like is a full language reference with some actual examples like you find for the languages I am more used to (HTML/CSS/JS/AS3), if such a thing exists.
Cheers for any help :)
I'm agree with #chepner's answer, but for google's results sake, to cd using pbpaste you simply do:
cd $(pbpaste)
When you use the %q format, you are adding literal backslashes to the string, which the shell does not process as escape characters when you use it with cd.
The clipboard is useful for interprocess communication; inside a single script, it's easier to just use variables to hold information temporarily. f already has the path name in it, so just use it:
cd "$f"
Notice I've quoted the expansion of f, so that any spaces in the path name are passed as part of the single argument to cd.

Bash script to cd to directory with spaces in pathname

I'm using Bash on macOS X and I'd like to create a simple executable script file that would change to another directory when it's run. However, the path to that directory has spaces in it. How the heck do you do this? This is what I have...
Name of file: cdcode
File contents:
cd ~/My Code
Now granted, this isn't a long pathname, but my actual pathname is five directories deep and four of those directories have spaces in the path.
BTW, I've tried cd "~/My Code" and cd "~/My\ Code" and neither of these worked.
When you double-quote a path, you're stopping the tilde expansion. So there are a few ways to do this:
cd ~/"My Code"
cd ~/'My Code'
The tilde is not quoted here, so tilde expansion will still be run.
cd "$HOME/My Code"
You can expand environment variables inside double-quoted strings; this is basically what the tilde expansion is doing
cd ~/My\ Code
You can also escape special characters (such as space) with a backslash.
I found the solution below on this page:
x="test\ me"
eval cd $x
A combination of \ in a double-quoted text constant and an eval before cd makes it work like a charm!
After struggling with the same problem, I tried two different solutions that works:
1. Use double quotes ("") with your variables.
Easiest way just double quotes your variables as pointed in previous answer:
cd "$yourPathWithBlankSpace"
2. Make use of eval.
According to this answer Unix command to escape spaces you can strip blank space then make use of eval, like this:
yourPathEscaped=$(printf %q "$yourPathWithBlankSpace")
eval cd $yourPathEscaped
You can use any of:
cd ~/"My Code"
cd ~/M"y Code"
cd ~/My" Code"
You cannot use:
cd ~"/My Code"
The first works because the shell expands ~/ into $HOME/, and then tacks on My Code without the double quotes. The second fails because there isn't a user called '"' (double quote) for ~" to map to.
cd ~/My\ Code
seems to work for me... If dropping the quotes but keeping the slash doesn't work, can you post some sample code?
This will do it:
cd ~/My\ Code
I've had to use that to work with files stored in the iCloud Drive. You won't want to use double quotes (") as then it must be an absolute path. In other words, you can't combine double quotes with tilde (~).
By way of example I had to use this for a recent project:
cd ~/Library/Mobile\ Documents/com~apple~CloudDocs/Documents/Documents\ -\ My\ iMac/Project
I hope that helps.
A single backslash works for me:
ry4an#ry4an-mini:~$ mkdir "My Code"
ry4an#ry4an-mini:~$ vi todir.sh
ry4an#ry4an-mini:~$ . todir.sh
ry4an#ry4an-mini:My Code$ cat ../todir.sh
#!/bin/sh
cd ~/My\ Code
Are you sure the problem isn't that your shell script is changing directory in its subshell, but then you're back in the main shell (and original dir) when done? I avoided that by using . to run the script in the current shell, though most folks would just use an alias for this. The spaces could be a red herring.
When working under Linux the syntax below is right:
cd ~/My\ Code
However when you're executing your file, use the syntax below:
$ . cdcode
(just '.' and not './')
use double quotes
go ()
{
cd "$*"
}
The very simple way of doing this is-
$ cd My\ Folder
In bash, run DIR command and in the results you would see that the folder or path names having space between them has been written in the results like this -
$dir
My\ Folder
New\ Folder
Use single quotes, like:
myPath=~/'my dir'
cd $myPath
Avoid ~ in scripts; use $HOME instead.
I had a similar problem now were I was using a bash script to dump some data. I ended up creating a symbolic link in the script folder with out any spaces in it. I then pointed my script to the symbolic link and that works fine.
To create your link.
ln -s [TARGET DIRECTORY OR FILE] ./[SHORTCUT]
Mau or may not be of use.
I read all these, and they didn't seem to work on macOS Monterey. I then changed the header from #!/bin/sh to #!/bin/zshand that seemed to do the trick.

Resources