0

Surely I'm missing something simple, but this is driving me nuts. I'm trying to SCP a remote file to the current local directory. The remote path has spaces in it. I need this to run in a script and put the path into a variable, because it's being read from a file.

Problem is, no matter how I try to escape it, I'm still getting a "File or Directory not found" error. I put the -v option on the scp command, and the command it's sending over works if I copy and paste it, but when I have the variable in there, it blows up.

Note that it works fine if I write out the path, but breaks when I try to put the path into a variable. There's lots of similar questions for just escaping a hard coded string, but I couldn't find anything for using variables with spaces in the filepath.

Path to file is: /home/myUser/databases/SONIC BOATS LTD./database-1.11-2019-12-30-09-40.zip

When running scp verbose, the line sending command prints the following:

 scp -f /home/myUser/databases/SONIC\\ BOATS\\ LTD./database-1.11-2019-12-30-09-40.zip . 

If I paste that line into my script and run it, then it works. So why isn't it working when it's running in the script with the variables?

My variables print out as follows:

DB_ARC_FILENAME:

/home/myUser/databases/SONIC BOATS LTD./database-1.11-2019-12-30-09-40.zip 

ESC_DB_ARC_FILENAME

/home/myUser/databases/SONIC\ BOATS\ LTD./database-19.11-2019-12-30-09-40.zip 

And my script code snippet:

while read DB_ARC_FILENAME do # Escape spaces in the files name ESC_DB_ARC_FILENAME=${DB_ARC_FILENAME//\ /\\\ } # Copy the database file to the local system scp -v [email protected]:"$ESC_DB_ARC_FILENAME" . ... done < uploadedDatabaseFileList 

Here's the output I'm getting when I run it:

debug1: Sending command: scp -v -f /home/myUser/databases/SONIC\\ BOATS\\ LRD./database-1.11-2019-12-30-09-40.zip debug1: client_input_channel_req: channel 0 rtype exit-status reply 0 debug1: client_input_channel_req: channel 0 rtype [email protected] reply 0 : No such file or directoryer/databases/SONIC BOATS LTD./database-1.11-2019-12-30-09-40.zip debug1: channel 0: free: client-session, nchannels 1 : No such file or directoryes/SONIC BOATS LTD./database-1.11-2019-12-30-09-40.zip debug1: fd 0 clearing O_NONBLOCK debug1: fd 1 clearing O_NONBLOCK Transferred: sent 2836, received 2704 bytes, in 0.8 seconds Bytes per second: sent 3678.9, received 3507.7 debug1: Exit status 1 
7
  • Does this answer your question? Problem in secure copying (scp) filenames with spacesCommentedJan 8, 2020 at 22:01
  • No - it works if I type out the filename, the problem arises when I put the filename into a variable.CommentedJan 8, 2020 at 22:02
  • Try replacing "$ESC_DB_ARC_FILENAME" with ${ESC_DB_ARC_FILENAME}
    – Ketan
    CommentedJan 8, 2020 at 22:24
  • @GillesQuenot I think your suggested duplicate isn't really a duplicateCommentedJan 8, 2020 at 22:34
  • That didn't change anything. I've updated my question with the output from scp with the verbose flag. It's the same with and without the braces.CommentedJan 8, 2020 at 22:35

2 Answers 2

1

Your escape pattern isn't quite right. Use this instead, which prefixes every occurrence of a space with a single backslash:

ESC_DB_ARC_FILENAME="${DB_ARC_FILENAME// /\\ }" 

Test scenario (in $HOME):

file='the date.txt' date > "$file" scp -vp localhost:"$file" td; ls -l td; rm -f td # Fails scp -vp localhost:"${file// /\\ }" td; ls -l td; rm -f td # Succeeds 

Got it. This error message gives it away:

: No such file or directoryes/SONIC BOATS LTD./database-1.11-2019-12-30-09-40.zip 

You're using a source data file generated on a Windows machine. The trailing CR is being seen as part of the filename, and of course your source file doesn't have such a character.

7
  • Unfortunately, that doesn't change the debug output or the result - i.e. I still can't get the file. I've tried playing with the escape pattern - the one in the question is just where I ended up.CommentedJan 8, 2020 at 22:39
  • Works for me. Are you sure you've double-quoted the variable when it's being used? Also... does the test scenario that I've provided work for you? If not we need to dig harder.CommentedJan 8, 2020 at 22:39
  • @TonyShepherd it's your source data fileCommentedJan 8, 2020 at 22:44
  • 1
    What tool generated it?CommentedJan 8, 2020 at 23:05
  • 2
    @TonyShepherd It's the -t in the ssh command that caused this to happen to you. Compare the output of ssh -t [email protected] date | hexdump -Cv with the output of ssh [email protected] date | hexdump -Cv. The former will have 0d0a line-endings, the latter won't.
    – Jim L.
    CommentedOct 14, 2021 at 19:59
0

I encountered similar issues when trying to copy files from remote paths containing spaces using scp from within a Bash script.

Here are the solutions I came up with:

Use double-quoting + option -T:

scp -T user@host:"'<path-with-spaces>'" <destination> scp -T user@host:'"<path-with-spaces>"' <destination> scp -T user@host:"\"<path-with-spaces>\"" <destination> 

Note: without option -T, these commands will result in protocol error: filename does not match request. The reason for this is discussed in detail here.

Escape path using printf:

source="<path-with-spaces>" printf -v source "%q" "${source}" scp user@host:"${source}" <destination> 

Note: this works fine without option -T, but only for a single file. For multiple files, option -T is required again (same error as above).

    You must log in to answer this question.

    Start asking to get answers

    Find the answer to your question by asking.

    Ask question

    Explore related questions

    See similar questions with these tags.