Файл копии Python scp с пробелами в имени файла

Я пытаюсь скопировать файлы в локальной сети с помощью scp. Он хорошо работает с именами файлов без пробелов, но сбой. Я пытался заменить " " на "\", так как это пример, но он не работает. Вот мой код:

def connection(locals):
         a = (int(re.search(br'(\d+)%$', locals['child'].after).group(1)))
         print a
         perc = (Decimal(a)/100)
         print (type(perc)), perc
         while gtk.events_pending():
             gtk.main_iteration()
         FileCopy.pbar.set_text("Copy of the file in the Pi...   " + str(a) + "%")
         while gtk.events_pending():
             gtk.main_iteration()
         FileCopy.pbar.set_fraction(perc)

file_pc = "/home/guillaume/folder/a very large name of file with space .smthg"
file_pi = "[email protected]:/home/pi/folder/a very large name of file with space .smthg"

if " " in file_pc:
   file_pc = fichier_pc.replace(" ", '\\\ ')   # tried '\\ ' or '\ '
   file_pi = fichier_pi.replace(" ", '\\\ ')   # but no way
else:
   pass
command = "scp %s %s" % tuple(map(pipes.quote, [file_pc, file_pi]))
pexpect.run(command, events={r'\d+%': connection}) # this command is using to get the %

Как я могу решить эту проблему? Спасибо


person Guillaume    schedule 29.03.2014    source источник
comment


Ответы (3)


Вы можете оставить локальный файл file_pc как есть (pipes.quote не будет пробелов). Удаленный файл должен быть изменен:

import pipes

file_pi = '[email protected]:/home/pi/folder/file with space.smth'
host, colon, path = file_pi.partition(':')
assert colon
file_pi = host + colon + pipes.quote(path)

т. е. user@host:/path/with space следует заменить на user@host:'/path/with space'

person jfs    schedule 29.03.2014
comment
Ты сильная. Спасибо! - person Guillaume; 29.03.2014

Используйте модуль subprocess и/или shlex.split():

import subprocess
subprocess.call(['scp', file_pc, file_pi])

и вам не нужно беспокоиться об экранировании или цитировании чего-либо

person m.wasowski    schedule 29.03.2014
comment
Нет, я не могу. Я хочу получить вывод команды, чтобы отобразить индикатор выполнения. (см. здесь - person Guillaume; 29.03.2014
comment
вывод отображается на стандартный вывод. Если вы не хотите, чтобы это было захвачено, чтобы реагировать в реальном времени... что ж, это можно сделать, но это очень хлопотно. Вам нужны потоки, повторное открытие дескриптора fd для процесса stdout с соответствующими флагами и т. д. Было бы лучше проверить модуль paramiko, но это совершенно другой вопрос. - person m.wasowski; 29.03.2014
comment
Я попробовал paramiko, но есть ошибка с большими файлами (см. здесь ). Как я уже сказал, скрипт отлично работает без пробелов в имени. - person Guillaume; 29.03.2014
comment
@m.wasowski: прочитайте мой ответ на вопрос, на который ссылается Гийом. Он показывает, что scp ничего не выводит, если stdout является каналом. Хотя он работает с псевдотерминалом, предоставляемым модулем pexpect (в этом случае проблем с буферизацией нет). Проблема в том, как передать имена файлов с пробелами в команду scp. - person jfs; 29.03.2014
comment
Хорошо, я дам другое решение, когда вернусь домой - person m.wasowski; 29.03.2014

Вы можете изучить fabric, библиотеку Python, которая упрощает использование SSH.

from fabric.state import env
from fabric.operations import get

env.user = 'username'
env.key_filename = '/path/to/ssh-key'

get('/remote_path/*', 'local_path/')
person rubayeet    schedule 29.03.2014
comment
fabric реализован поверх paramiko, который не работает для больших файлов - person jfs; 29.03.2014