How does one escape the " ` " (accent grave/backtick) in a path?

I tend to prefix oft-used files and folders with the "accent grave" character (non-shift tilde, the back-tick, or plain-old accent, whathaveyou..), as it is easy to get at, and let's me sort things alphabetically, while letting me choose to show a few items on the top. It works nicely, except when I go to access these files via the CLI or SSH/SCP.

If I try to run a command, calling the file unescaped ↝ it kicks me into an interactive session.. for example ↯

# scp -r dns.local:/`Downloads/CrazyRussianCars/ ~/
↩
>

Yet if I try the logical solution ↯

# scp -r dns.local:/\`Downloads/CrazyRussianCars/ ~/
↩
bash: -c: line 0: unexpected EOF while looking for matching ``'
bash: -c: line 1: syntax error: unexpected end of file

I know the "new" rule is to use a syntax like export NOW=$(date) vs export NOW= `date` (in fact, I had a bear of a time even writing the latter in SE MD syntax...) but this is unrelated to the ENV or any script...

Note: This is a Mac OS X environment, but that said, the GUI has never had a problem dealing with this character on a day-to-day basis, and usually, if there's going to be a syntax problem in the Terminal, Apple does a pretty good job of disabling the behavior in the GUI... Not sure if this is a bug, or if the technique for dealing with such paths is simply obscure.. but so far, I have been un-able to find a way "to escape it"?


Solution 1:

You can use 3 backslashes as mentioned by Jed Daniels or you can wrap it in single quotes (') and use a single backslash.

Example of both are below.

$ touch dir/'`rik' 
$ ls -l dir
total 1865376
-rw-r--r--  1 rik  staff          0 Jul  1 09:51 `rik 
$ scp localhost:dir/\\\`rik ./ `rik         
100%    0     0.0KB/s   00:00     
$ scp localhost:dir/'\`rik' ./ `rik     
100%    0     0.0KB/s   00:00     
$

Solution 2:

Three backslashes should do it:

jed@jed-osx:~$ ls -la \`foo
ls: `foo: No such file or directory
jed@jed-osx:~$ scp desk:\\\`foo .
`foo                                            100%    0     0.0KB/s   00:00    
jed@jed-osx:~$ ls -la \`foo
-rw-r--r--  1 jed  staff  0 Jul  1 09:45 `foo
jed@jed-osx:~$ rm \`foo

The first backslash escapes the backtick so it gets sent to the other side, but the other side throws the error because it is expecting backticks to be in pairs. The second backslash escapes the first backslash, then you need the extra two backslashes so you can send an escaped backslash to the other side.

EDIT: As Rik mentions, you can also do it with a single quote. I hadn't thought of this because you can't us it with variables (they won't get expanded on the local system when in the single quotes).

Solution 3:

Normally, command lines get interpreted by the shell once. However, for historical reasons, scp passes the file name to the remote shell as well, so the file name gets interpreted by shells twice. This is also what makes things like scp remote:'/path/prefix*' /path/local/ work, the remote shell is expanding /path/prefix*.

The easiest way to avoid the second expansion is to use sftp, which doesn't use a remote shell. It still does glob expansion, but since you can give it commands on stdin, you can avoid your local shell expansion entirely.

Other than that, you can use any of the normal shell quoting mechanisms, including those given by @Jed Daniels and @Rik Schneider, but I wanted to explain what's actually happening and mention sftp.

(You can use all kinds of shell features in your scp filename, for example scp server:\$HOME/file dest will use the remote shell's idea of $HOME, whereas if you took out the \, it'd use your local shell's.).