子进程命令没有使用ls命令查找文件?

fly*_*zai 6 python subprocess python-2.6

我正在创建一个程序,它将提取一个帐号列表,然后运行一个ls -lh命令来查找每个帐号.当我在没有Python的Linux服务器上运行我的命令时,它会提取文件没问题,但是当我通过Python执行它时它说它无法找到它们.

import subprocess as sp
sp.call(['cd', input_dir])
for i, e in enumerate(piv_id_list):
    proc_out = sp.Popen(['ls', '-lh', '*CSV*APP*{0}.zip'.format(e)])
    proc_out_list.append(proc_out)
    print(proc_out)
Run Code Online (Sandbox Code Playgroud)

这是通过Python解释器运行命令时的一些示例输出:

>>> ls:无法访问*CSV1000*APP*:没有这样的文件或目录

但是通过Linux同样的命令:

ls -lh *CSV*APP*
Run Code Online (Sandbox Code Playgroud)

它会像它应该的那样返回输出.

Jun*_*sor 5

这是因为shell使用与模式匹配的现有文件替换通配符.例如,如果你有a.txtb.txt,然后ls *.txt将从外壳扩展ls a.txt b.txt.使用您的命令,您实际上要求ls返回有关其文件名中包含星号的文件的信息.如果要验证,请使用以下内容:

sp.Popen(['bash', '-c', 'ls', '-lh', '*CSV*APP*{0}.zip'.format(e)])
Run Code Online (Sandbox Code Playgroud)

您还应该使用os.chdir更改目录,因为sp.call(['cd', input_dir])更改了您创建的新进程的当前目录,而不是父目录.

  • 当然是.这就是我要做的.你不会有像`ls`这样的外部依赖,它可以在其他操作系统上运行,而且并不困难...... (2认同)

das*_*s-g 3

ls通过 Python 运行时,可能是正确的:我猜当前目录中没有调用任何文件。*CSV*APP*可能存在一个名称与该全局模式匹配的文件。但ls不关心全局。当您在 shell 上运行该命令时,会发生什么情况:shell 将 glob 扩展为它可以在当前目录中看到的匹配文件名,并且这些扩展名称是 shell 传递给ls.

要在 shell 中获得与 Python 中相同的结果(用于演示,而不是因为您想要这样),请使用单引号保护参数免遭全局扩展:

ls -lh '*CVS*APP*'${e}'.zip'
Run Code Online (Sandbox Code Playgroud)

但是如何在 Python 中获得 shell 的行为呢?您可以使用shell=True,但这是一个滑坡,因为在动态生成的字符串上调用实际的 shell(可能取决于更复杂的应用程序中的用户输入)可能会使您容易受到命令注入和其他恶意行为的影响。

在这里,您需要shell 的一种特定行为,即文件名匹配。Python 恰好能够自己完成这一切

import subprocess as sp
from glob import glob
sp.call(['cd', input_dir])
for i, e in enumerate(piv_id_list):
    proc_out = sp.Popen(['ls', '-lh', glob('*CSV*APP*{0}.zip'.format(e))])
    proc_out_list.append(proc_out)
    print(proc_out)
Run Code Online (Sandbox Code Playgroud)

正如JuniorCompressor 所指出的,这仍然会在错误的目录中查找,因为这cd只会影响调用的子进程,所以cd让我们也修复这个问题:

import subprocess as sp
from glob import glob

os.chdir(input_dir)
for i, e in enumerate(piv_id_list):
    proc_out = sp.Popen(['ls', '-lh', glob('*CSV*APP*{0}.zip'.format(e))])
    proc_out_list.append(proc_out)
    print(proc_out)
Run Code Online (Sandbox Code Playgroud) 笔记

您可能可以直接使用稍高级别的sp.check_output层而不是底层sp.Popen