Reputation: 44381
Somebody came up with the brilliant idea of putting spaces in a filename. I need to do scp from python using that filename, which is problematic because the shell parses the command, and scp has also some quircks regarding spaces. This is my test code:
import subprocess
import shlex
def split_it(command):
return shlex.split(command)
#return command.split(" ")
def upload_file(localfile, host, mypath):
command = split_it('scp {} {}:"{}"'.format(localfile, host, mypath))
print(command)
res = subprocess.run(command, stdout=subprocess.PIPE)
return res.stdout.decode()
upload_file("localfile.txt", "hostname", "/some/directory/a file with spaces.txt")
Which gives:
['scp', 'localfile.txt', 'hostname:/some/directory/a file with spaces.txt']
scp: ambiguous target
Using the naive version with command.split(" ")
:
['scp', 'localfile.txt', 'hostname:"/some/directory/a', 'file', 'with', 'spaces.txt"']
spaces.txt": No such file or directory
The right, working scp command would be:
['scp', 'localfile.txt', 'hostname:"/some/directory/a file with spaces.txt"']
split_it('scp localfile.txt hostname:"/some/directory/a file with spaces.txt"')
# returns ['scp', 'localfile.txt', 'hostname:"/some/directory/a file with spaces.txt"']
Upvotes: 2
Views: 2514
Reputation: 23192
command = split_it('scp {} {}:"{}"'.format(localfile, host, mypath))
Instead of building a command string, only to split_it
again, directly build a list of arguments.
In order to add one layer of quoting to the remote file path, use shlex.quote
(or pipes.quote
if using older Python versions).
command = ['scp', localfile, '{}:{}'.format(host, shlex.quote(mypath))]
Sources/related posts:
Upvotes: 4