这个最小的例子:(在PyCharm调试器中运行)
import os
from os.path import join
import subprocess
src_path = r'C:/TEMP/source'
dest_path = r'C:/TEMP/dest'
if __name__ == "__main__":
for root, _, files in os.walk(src_path):
for name in files:
src_file_path = join(root, name)
rel_dest_file_path = os.path.join(dest_path, os.path.dirname(os.path.relpath(src_file_path, src_path)))
rdfp = join(rel_dest_file_path, name)
sfp = src_file_path
cmd = "['copy', '/v', %s, %s]" % (sfp, rdfp)
print 'calling shell subprocess %s' % cmd
subprocess.call(['copy', '/v', sfp, rdfp], shell=True)
生成以下输出:
calling shell subprocess ['copy', '/v', C:/TEMP/source\foo bar.txt, C:/TEMP/dest\foo bar.txt]
1 file(s) copied.
calling shell subprocess ['copy', '/v', C:/TEMP/source\foo.txt, C:/TEMP/dest\foo.txt]
The syntax of the command is incorrect.
Process finished with exit code 0
为什么文件名为“foo bar.txt”的路径不会产生命令语法错误?为什么路径会导致成功的文件复制?
我可以通过在初始的原始字符串文本路径赋值中显式使用Windows路径分隔符来修复示例中的语法问题,这对我来说是有意义的。
src_path = r'C:\TEMP\source'
dest_path = r'C:\TEMP\dest'
令人不解的是,为什么“混合斜线”路径中的空格也能“解决”语法问题。
有什么参考资料或指示吗?
1条答案
按热度按时间x7yiwoj41#
简短的回答是:* * 保持一致,始终使用操作系统首选的分隔符。**不要依赖于意外发生的情况来保护您。
您的具体情况说明:在Windows系统中,程序是用一个字符串启动的,而不是像POSIX系统中那样用一个参数向量启动的。你传递了一个
list
作为命令,这意味着它必须被转换成一个字符串。Python用一个内部函数list2cmdline
来完成这一操作。它在空参数以及任何包含空格或制表符的参数周围添加引号。结果是,你的代码只有在路径中有空格时才用引号括起来:看起来
copy
的参数解析可以接受路径中的反斜杠,如果路径被引用,但不被引用,它会变得混乱(可能是因为解析器将未受保护的正斜杠视为引入了奇怪的开关)。这里一个更普遍的规则是WinAPI调用可以使用混合分隔符,但是单个程序的参数解析可能不行。但是同样,首先跳过这个问题,使用
os.path.join
、os.sep
、Path
对象的/
重载等,而不是硬编码路径(除非路径受到操作系统的限制,无法存在于不匹配的操作系统上,例如,在您的情况下,您使用的是Windows,只有Windows路径,应该只使用带反斜杠的原始字符串常量)。