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
Which Linux Ipc Technique to Use
How to Compare Two Datetime Strings and Return Difference in Hours? (Bash Shell)
"/Usr/Bin/Ld: Cannot Find -Lz"
Return Value of Sed For No Match
Modify Qt Gui from Background Worker Thread
How to Upgrade Glibc from Version 2.12 to 2.14 on Centos
Asynchronous Io Io_Submit Latency in Ubuntu Linux
Execute Command After Every Command in Bash
How Is Stack Memory Allocated When Using 'Push' or 'Sub' X86 Instructions
How to Print a Character in Linux X86 Nasm
How to Run a Shell Script on a Unix Console or MAC Terminal
What Does Localhost Means Inside a Docker Container
Take Nth Column in a Text File
Disable Randomization of Memory Addresses
How to Get Gcc to Output Raw Binary
How to Write Data to Existing Process'S Stdin from External Process