1

我正在尝试在 python 脚本中执行 find 命令,使用 for 循环传递变量索引来确定要查找的特定文件名。我正在使用以下语法,它在 python 中返回一个空集,但在终端中有效:

for j in [1,2,3,5]:  
    file_name = cmd.getoutput('find . -type f -name "*${j}-xyz.stc" -printf "%f\n"')

显然,该变量没有被传递给我的 python 代码中的 find 表达式,但我该如何补救呢?任何建议表示赞赏。

4

3 回答 3

3

变量在 python 中的扩展与在 bash 中的扩展不同。你可能想要:

command = r'find . -type f -name "*{0}-xyz.stc" -printf "%f\n"'.format(j)
file_name = cmd.getoutput(command)

另请注意,该commands模块已弃用,取而代之的是subprocess. 最后,可能应该指出的是,您可以在python中编写此函数,而无需依赖find是否os.walkglob.glob.

未经测试,但这样的事情应该很接近......

import os
import glob

def find_files(glob_expr):
    for root,_,_ in os.walk(os.curdir):
        for fname in glob.iglob(os.path.join(os.curdir,root,glob_expr)):
            yield fname
for i in (1,2,3,4):
    print (list(find_files('{0}-xyz.stc'.format(i))))
于 2012-08-29T21:58:07.930 回答
2
file_name = cmd.getoutput('find . -type f -name "*%i-xyz.stc" -printf "%%f\n"' % (j))
于 2012-08-29T21:57:57.193 回答
1

Passing filenames in a string to the shell is unsafe (leads to potentially security-impacting bugs). Best practice is to pass an explicit argv list:

import subprocess
for j in range(1, 6):
    file_name = subprocess.check_output(['find', '.', '-type', 'f', '-name',
                                         '*%s-xyz.stc' % (j,),
                                         '-printf', '%f\\n'])

If you really care about correctness (and you should!), use '%f\\0' as your format string, and expect your outputs to be NUL-separated. Otherwise, you can't tell the difference between a file with a newline in its name and two files returned.

To appreciate the importance, consider the case where an attacker can persuade software running on your system to create a file named like so:

/your/top/dir/$'\n'/etc/passwd$'\n'/1-xyz.stc

If you treat each line returned by find as a filename, you would consider /etc/passwd to be part of your returned values -- a very bad thing if you then present this data to the user, delete it, etc.

于 2012-08-29T23:30:14.600 回答