在子进程中使用*通配符的命令问题

时间:2012-09-04 16:34:09

标签: python copy subprocess cp glob

我正在尝试使用子进程库和Popen方法将文件从一个位置复制到另一个位置。运行以下脚本时,我收到错误cp: cannot stat /some/dev_path/*。有人告诉我,*没有扩展到文件名,这就是问题所在。另外在其他一些帖子中,人们建议使用呼叫代替Popen,但就我所知,呼叫不会返回stderr。

devPath = '/some/dev_path/'
productionPath = '/some/prod_path/'

p = subprocess.Popen(['cp', '-r', devPath + '*', productionPath], stdout = subprocess.PIPE, stderr = subprocess.PIPE)
pout, perr = p.communicate()

if perr != '':
    sys.exit('Error: ' + perr)

1 个答案:

答案 0 :(得分:13)

扩展*(globbing)是shell的一个函数,例如 bash 。因此,您必须在shell=True电话中使用关键字参数subprocess.Popen

但是,对于这种情况,我强烈建议改为使用shutil.copytree

(首先,因为它更简单(参见Zen of Python)并且不易出错。处理错误更加清晰,你会得到很好的例外,包括错误列表(用于多文件操作)像你一样),你不必处理产生子进程并与之通信。其次,如果你不需要,分叉子进程是不必要的资源浪费。其他问题包括引用/转发和可能如果您无法正确清理用户输入,请在代码中引入安全漏洞。)

例如:

from shutil import copytree
from shutil import Error

try:
   copytree('dir_a', 'dir_b')
except (Error, OSError), e:
    print "Attempt to copy failed: %s" % e

此外,您不应通过将字符串连接在一起来构建文件系统路径,而应使用os.path.join()。这将为当前操作系统使用正确的目录分隔符(os.sep),并允许您轻松编写可移植代码。

示例:

>>> import os
>>> os.path.join('/usr/lib', 'python2.7')
'/usr/lib/python2.7'

注意:os.path.join仍然只进行(智能)字符串操作 - 它不关心该路径是否可访问或存在。