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

时间:2022-03-23 00:24:51

I'm trying to copy files from one location to another using subprocess library and Popen method. When runing following script I'm getting the error cp: cannot stat /some/dev_path/*. I was told that the * is not expanded to the file names and that's where the problem is. Also in some other posts people were suggesting to use call instead of Popen, but call will not return stderr as far as I know.

我正在尝试使用子进程库和Popen方法将文件从一个位置复制到另一个位置。运行以下脚本时,我收到错误cp:不能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 个解决方案

#1


13  

Expanding the * (globbing) is a function of your shell, bash for example. Therefore you'd have to use the keyword argument shell=True in your subprocess.Popen call.

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

However, for this case I'd strongly suggest to use shutil.copytree instead.

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

(First of all, because it's much simpler (see Zen of Python) and less error-prone. Dealing with errors is much cleaner, you get nice exceptions including a list of errors (for multi file operations like yours), and you don't have to deal with spawning a subprocess and communicating with it. Second, it's an unnecessary waste of resources to fork a child process if you don't need to. Other issues include quoting / escaping and possibly introducing security vulnerabilities into your code if you fail to properly sanitize user input.)

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

For example:

例如:

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

Also, you shouldn't build filesystem paths by concatenating strings together, but instead use os.path.join(). That will use the correct directory separator (os.sep) for the current OS and allow you to easily write portable code.

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

Example:

例:

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

Note: os.path.join still only does (smart) string manipulation - it doesn't care if that path is accessible or even exists.

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

#1


13  

Expanding the * (globbing) is a function of your shell, bash for example. Therefore you'd have to use the keyword argument shell=True in your subprocess.Popen call.

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

However, for this case I'd strongly suggest to use shutil.copytree instead.

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

(First of all, because it's much simpler (see Zen of Python) and less error-prone. Dealing with errors is much cleaner, you get nice exceptions including a list of errors (for multi file operations like yours), and you don't have to deal with spawning a subprocess and communicating with it. Second, it's an unnecessary waste of resources to fork a child process if you don't need to. Other issues include quoting / escaping and possibly introducing security vulnerabilities into your code if you fail to properly sanitize user input.)

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

For example:

例如:

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

Also, you shouldn't build filesystem paths by concatenating strings together, but instead use os.path.join(). That will use the correct directory separator (os.sep) for the current OS and allow you to easily write portable code.

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

Example:

例:

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

Note: os.path.join still only does (smart) string manipulation - it doesn't care if that path is accessible or even exists.

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