如果您打印了测试字符串,您会注意到它会产生以下结果:
su -c "lftp -c 'open -u user,password ftp://127.0.0.1; get ivan's\ filename.pdf' " someuser
问题是你需要转义用于转义单引号的斜杠,以防止 Python 吃掉它。
command = "su -c \"lftp -c 'open -u user,password ftp://127.0.0.1; get ivan\\'s\\ filename.pdf' \" someuser"
会得到反斜杠,然后你会从lftp得到一个错误......
这有效:
command = "su -c \"lftp -c \\\"open -u user,password ftp://127.0.0.1; get ivan\\'s\\ filename.pdf\\\" \" someuser"
(它使用(转义的)双引号来代替,以确保由 su 启动的 shell 仍然解释转义序列)
(os.system(a)
有效地做到了subprocess.call(["sh","-c",a])
, 意思就是sh
sees su -c "lftp -c 'open -u user,password ftp://127.0.0.1; get ivan's\ filename.pdf' " someuser
(对于原来的)。它对此进行转义序列处理,并看到一个未闭合的单引号(它最初由ivan'
),导致你的错误)。一旦这个问题解决了,sh
调用 su,它又启动另一个实例sh
进行更多的转义处理,导致来自lftp的错误(因为sh
不处理单引号中的转义序列)
subprocess.call()
or curl
是更好的方法来实现这一点 -curl
需要更少的转义,你可以使用curl "ftp://user:[email protected]/ivan's filename.pdf" on the command line, some more escaping is needed for going via
su -cand for python.
sudoinstead of
su` 也导致需要更少的转义......
如果你想使用subprocess.call()
(去除一层外壳),你可以使用
subprocess.call(["su","-c","lftp -c \\\"open -u user,password ftp://127.0.0.1; get ivan\\'s\\ filename.pdf\\\"", "someuser"])
(问题是 python 处理一级转义,并且sh -c
调用自su
与下一层...这会导致一个相当丑陋的命令...)(不同的引号可能会稍微减少...)
Using r""
可以摆脱python级别的转义处理:(只需要shell级别的转义)(使用三引号允许在字符串中使用引号)
subprocess.call(["su","-c",r"""lftp -c \"open -u user,password ftp://127.0.0.1; get ivan\'s\ filename.pdf\"""", "someuser"])
添加空格可以去除 shell 转义符,因为lftp
似乎不需要对空格和单引号进行转义的文件名。
subprocess.call(["su","-c",r"""lftp -c "open -u user,password ftp://127.0.0.1; get ivan's filename.pdf" """, "someuser"])
这导致最终的结果是lftp
ARGV 正在
["lftp","-c","open -u user,password ftp://127.0.0.1; get ivan's filename.pdf"]
对于卷曲(由于su
参与):
subprocess.call(["su","-c",r"""curl "ftp://user:[email protected]/ivan's filename.pdf" """, "someuser"])