How to Escape Spaces in Path For Scp Copy in Linux

How to scp a directory with a space in the name

As detailed in this answer, you need to use two sets of quotes, because the filename is interpreted twice: once by the local computer and once by the remote computer.

scp -i key -r "$current_dir/$dir_name" user@$ip:"'$current_dir/$dir_name'"

How to escape & in scp

Escaping both the spaces and the ampersand did the trick for me :

scp source_file "user@host:/dir\ with\ spaces\ \&\ ampersand"

The quotes are still needed for some reason.

How to properly escape spaces form multiple files in an scp command in a sourced function in bash

First, change your calling signature so that the suffix comes first:

push2 42 ./temp*

Then the function should be defined simply as

push2 () {
local -a scpProxy
local prefix suffix
suffix=$1
shift

gen_prefix "$suffix"

scp "${scpProxy[@]}" "$@" "testuser@$prefix.$suffix:"
}

where gen_prefix looks something like

gen_prefix () {
case $1 in
42) scpProxy=()
prefix=10.3.3
;;
89) scpProxy=(-o ProxyJump=user@server)
prefix=123.456.789
;;
esac
}

After calling shift, $@ contains just the files you want to transfer. scpProxy is an array that holds multiple individual arguments to pass to scp; if it is empty, then "${scpProxy[@]}" will expand to 0 arguments, not the empty string.

(Using ./temp* instead of temp* guards against matches that contain : and could thus be mistaken for a remote file name.)

Although gen_prefix appears to define its variables "globally", it's really just defining them in whatever scope gen_prefix is called from (bash uses dynamic scoping, not lexical scoping, like most other common languages). The two calls to local ensure that whatever gen_prefix assigns stays inside push2, and not visible after push2 exits.


As an additional note, much of this function can go away with a suitable ssh configuration. Consider this in your .ssh/config file:

Host somehost
User testuser
Hostname 10.3.3.42

Host someotherhost
User testuser
Hostname 123.456.789.89
ProxyJump user@server

Now you don't need push2 at all; just run

scp temp* somehost:

or

scp temp* someotherhost:

and the correct addresses and options will be used automatically. The ssh configuration replaces everything gen_prefix did, and without the need to call gen_prefix, there's no longer any need to wrap scp.

How to copy using scp on shell script to folders space named?

This is tricky because it requires multiple levels of escaping.

First, start with the actual path:

home@192.X.X.X:/Users/home/Documents/New Files/

Now escape it for the shell:

"home@192.X.X.X:/Users/home/Documents/New Files/"

Now escape it for scp, since scp accepts shell glob patterns and not filenames:

/usr/bin/scp /home/pi/"${1}" "home@192.X.X.X:/Users/home/Documents/New\\ Files/"

Now escape it for ssh, since ssh will evaluate it in a shell:

/usr/bin/ssh pi@192.168.25.144 \
/usr/bin/scp /home/pi/"${1}" \
'"home@192.X.X.X:/Users/home/Documents/New\\ Files/"'

This takes care of the "New Files" part, but let's also try to do something about the "${1}" argument:

/usr/bin/ssh pi@192.168.25.144 \
/usr/bin/scp /home/pi/"$(printf "%q" "$1")" \
'"home@192.X.X.X:/Users/home/Documents/New\\ Files/"'

Here's a complete, self contained example of the above, going through localhost twice:

#!/bin/bash
cd ~
mkdir "New Files"
touch "my file"
set -- "my file" # Assign $1="my file"
/usr/bin/ssh localhost \
/usr/bin/scp "$(printf "%q" "$1")" \
'"localhost:New\\ Files/"'

find "New Files" -type f

The output shows that it did in fact copy a file with spaces over scp over ssh to the dir with spaces:

New Files/my file

Since multilevel escaping is tricky, if you're having any problems, make sure to try this self contained example first without modifications before concluding that it doesn't work.

Unable to pass filename with space through variable to SCP command

Try to double quote the var:

file="Unavailable Voucher's Report_Apr-2017.txt"
scp "$file" user@remoteserver:/path

Get input from user to path which contains a space (bash-script)

If both ends are using bash, you can use @Q parameter expansion:

read -r -p "Plot date: " plot_date
scp -r user@server:/home/user/Documents/projects/pages/"${plot_date@Q}" Plots/
${parameter@operator}
Parameter transformation. The expansion is either a transforma‐
tion of the value of parameter or information about parameter
itself, depending on the value of operator. Each operator is a
single letter:

Q The expansion is a string that is the value of parameter
quoted in a format that can be reused as input.

Is there a way to escape linux commands?

You can run an external command without a shell (and therefore without issues with shell metacharacters) using child_process.spawn (or other methods in child_process). (Obviously, you must not specify the shell option as anything other than the default false.)

That lets you not worry about metacharacters in the filepath, but it seems to me that there are plenty of other issues with letting the user provide a filepath name to be used as such on a live filesystem. Personally, I'd autogenerate safe, short names and keep the correspondence from user name to filesystem name in a database somewhere.



Related Topics



Leave a reply



Submit