Python - 使用Popen执行具有多个条件的查找

5

我想在多个条件下执行 find 命令,例如:查找 foo ,但排除隐藏文件:

find . -type f \( -iname '*foo*' ! -name '.*' \)

Python代码:

import subprocess

cmd = ["find", ".", "-type", "f", "(", "-iname", "*foo*", "!", "-name", ".*", ")"]
sp = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
print sp.communicate()[0].split()

有人可以解释一下我错过了什么吗?谢谢!


2
顺便提一句,使用 os.path.walk 你可以轻松实现一个纯Python风格的遍历,无需外部子进程。 - Jakub M.
我也遇到了同样的问题,即使没有排除隐藏文件。 - rschwieb
你得到了什么错误?你应该使用 -print0.split('\0') - jfs
3个回答

1
我也遇到了这个问题,我相信你现在已经解决了,但我想说一下以防其他人遇到同样的问题。事实证明,当你使用Popen时,Python实际上正在做什么(当使用shell=True时,Python基本上只是使用/bin/sh -c来传递你的命令(Python's subprocess.Popen() results differ from command line?)。默认情况下,shell为False,因此如果您省略它或将其设置为False,则将使用“executable”中指定的任何内容。文档在这里提供了更多详细信息:https://docs.python.org/2/library/subprocess.html#subprocess.Popen
类似以下内容应该可以工作:
import subprocess
cmd = 'find . -type f -iname "*foo*" ! -name ".*"'
sp = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
print sp.communicate()[0].split()

Popen 不会运行 /bin/sh,除非你使用 shell=True 来请求它。 - jfs
我已根据您的评论进行了澄清。据我所知,这仍然有效。 - idofxeno
1
问题中的代码可以直接使用,不需要添加 shell=True - jfs
奇怪——如果我不加上shell=True,我的代码就会崩溃。dir_list = subprocess.Popen(command, stdout=subprocess.PIPE) 然后调用wait等待退出码,out, err = dir_list.communicate() 并返回输出。编辑刚刚发现我们的服务器正在使用2.6.6——如果更新到2.7可以解决我的问题,我会进行编辑。 - idofxeno
你应该使用列表参数,例如 shlex.split(cmd) - jfs
谢谢你的建议,我会试一试(在我升级 Python 后)。 - idofxeno

0
在Python 3.7的subprocess.run()中,您可以将以空格分隔的cmd放入列表中,但字符串也可以正常工作。
然而,在subrocess.run()的文档中并没有提到这一点。
我无法让命令扩展为列表正常工作,但字符串却可以正常工作。
cmd = "find . -type f -iname \*foo\* ! -name .\\*"
print(cmd)
ret = subprocess.run(cmd, shell=True, capture_output=True)
print(ret)

测试:

$ find . -type f -iname \*foo\* ! -name .\*
./foobar.txt
./barfoo.txt

$ ./findfoo.py
find . -type f -iname \*foo\* ! -name .\*
CompletedProcess(args='find . -type f -iname \\*foo\\* ! -name .\\*',
 returncode=0, stdout=b'./foobar.txt\n./barfoo.txt\n', stderr=b'')

-1

至少需要在那里转义 *。

其次,通过反斜杠转义 ( 和 )(将 "\\(" 和 "\\)" 传递给 shell)

cmd = ["find", ".", "-type", "f", "\\(", "-iname", "\\*foo\\*", "!", "-name", ".\\*", "\\)"]

或者甚至只是去掉那些(和)-
cmd = ["find", ".", "-type", "f", "-iname", "\\*foo\\*", "!", "-name", ".\\*"]

应该可以正常工作


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接