I'm trying to copy a file using scp
in bash
with a colon (:
) character in the source filename. The obfuscated version of my command I'm using is:
scp file\:\ name.mp4 user@host:"/path/to/dest"
I get this error:
ssh: Could not resolve hostname Portal 2: Name or service not known
I know I could just rename the file and remove the :
, but I'd like to know if it's possible to escape the colon.
Not quite a bash
escaping problem, it's scp
treating x:
as a [user@]host prefix, try:
scp ./file:\ name.mp4 user@host:"/path/to/dest"
Using relative (e.g. ./
) or fully qualified paths (/path/to/source
) prevents this behaviour - the presence of /
before a :
causes OpenSSH to stop checking for a possible host:
or user@host:
prefix).
OpenSSH's scp
only special-cases filenames that start with a colon allowing those to work without problems, it has no support for escaping a :
in the normal sense, and has no other notion of valid hostnames so almost any filename with a :
can cause this (or equivalent IPv6 behaviour if [
]
are found before :
).
This can also affect other programs, e.g. rsync
, the same workaround applies there.
(Due to OpenSSH's simplistic parsing of []
enclosed IPv6 addresses, you can successfully scp
files containing :
which start with [
, or contain @[
before the :
and do not contain ]:
, but that's not generally useful ;-)
(The below text was written when the original question was How do I escape a colon in bash? It applies to that situation, but not to scp
as no amount of shell escaping will help there.)
To answer the question about how to escape :
, you don't need to, but "\:
" works. Places that a :
is used:
:
, no need to escape, though you can, just like \e\c\h\o foo
it has no effect on the command ("no effect" is not completely true, if you escape one or more characters it will prevent an alias being matched, and you can alias :
)PATH
(and others, CDPATH
, MAILPATH
) escaping the values has no useful effect (I have been unable to run a program in my PATH from a directory containing a :
, which is a little unexpected)${name:-x}
and more, name
must be [a-zA-Z_][a-zA-Z0-9_]
, so no need to escape variables names, and since there's no ambiguity, no need to escape subsequent :
in the other variations of parameter expansion? :
trinary operates only on variables and numbers, no need to escape==
and =~
with classes in the pattern like [[:digit:]]
, you can escape with \:
but I'm at a loss as to how that might ever be useful...\:
has no useful effect(Note that the null command is just :
, you can have a command or function named like ":foo
" and it can be invoked without escaping, in this respect it's different to #
where a command named #foo
would need to be escaped.)