在python脚本中查找具有变量名的文件

在python脚本中查找具有变量名的文件,python,linux,shell-exec,Python,Linux,Shell Exec,我试图在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表达式,但是我该如何补救呢?非常感谢您的建议。变量在pyt

我试图在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表达式,但是我该如何补救呢?非常感谢您的建议。

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

file_name = cmd.getoutput('find . -type f -name "*%i-xyz.stc" -printf "%%f\n"' % (j))
command = r'find . -type f -name "*{0}-xyz.stc" -printf "%f\n"'.format(j)
file_name = cmd.getoutput(command)
还请注意,
命令
模块被弃用,取而代之的是
子流程
。最后,可能需要指出的是,如果将
os.walk
glob.glob
结合使用,则可以用python编写此函数,而无需依赖
find

未经测试,但类似的东西应该很接近


python中变量的扩展方式与bash中的不同。您可能想要:

command = r'find . -type f -name "*{0}-xyz.stc" -printf "%f\n"'.format(j)
file_name = cmd.getoutput(command)
还请注意,
命令
模块被弃用,取而代之的是
子流程
。最后,可能需要指出的是,如果将
os.walk
glob.glob
结合使用,则可以用python编写此函数,而无需依赖
find

未经测试,但类似的东西应该很接近


以字符串形式将文件名传递给shell是不安全的(可能会导致影响安全性的bug)。最佳做法是传递一个明确的
argv
列表:

import subprocess
for j in range(1, 6):
    file_name = subprocess.check_output(['find', '.', '-type', 'f', '-name',
                                         '*%s-xyz.stc' % (j,),
                                         '-printf', '%f\\n'])
如果您真的关心正确性(而且您应该!),请使用
'%f\\0'
作为格式字符串,并期望输出是NUL分隔的。否则,您无法区分名称中有换行符的文件和返回的两个文件之间的区别

为了理解其重要性,考虑攻击者可以说服系统上运行的软件创建一个名为SO:

的文件的情况。
/your/top/dir/$'\n'/etc/passwd$'\n'/1-xyz.stc

如果您将查找到的每行返回为文件名,您会认为<代码> /ETC/PasWD < /C>是返回值的一部分——如果您将此数据呈现给用户、删除它等,则是非常糟糕的事情。

< P>将字符串中的文件名传递给shell是不安全的(导致潜在的安全影响错误)。最佳做法是传递一个明确的
argv
列表:

import subprocess
for j in range(1, 6):
    file_name = subprocess.check_output(['find', '.', '-type', 'f', '-name',
                                         '*%s-xyz.stc' % (j,),
                                         '-printf', '%f\\n'])
如果您真的关心正确性(而且您应该!),请使用
'%f\\0'
作为格式字符串,并期望输出是NUL分隔的。否则,您无法区分名称中有换行符的文件和返回的两个文件之间的区别

为了理解其重要性,考虑攻击者可以说服系统上运行的软件创建一个名为SO:

的文件的情况。
/your/top/dir/$'\n'/etc/passwd$'\n'/1-xyz.stc

如果您将查找到的每行返回为文件名,您会认为<代码> /ETC/PasWD < /C>是返回值的一部分——如果您将此数据呈现给用户,删除它,这将是一件非常糟糕的事情,等等。

如果你想使用旧字符串插值,你需要加倍
%%f
。如果你想使用旧字符串插值,你需要加倍
%%f
。我不能说我完全理解你的意思,但你的建议很有魅力。谢谢。@user1634460--您试图以shell中的方式(例如,
${j}
)展开变量
j
。然而,在python中它不是这样工作的。您需要在字符串中插入特殊标记,告诉字符串如何替换为值。在这种情况下,
{0}
意味着用相应的
格式
方法调用中的第一个值替换该字符串。@Abuser3.145159它之所以有效,是因为您没有用足够有趣的输入来尝试它——如果字符串中有双引号,或者看起来像是变量解引用,或者(更糟糕!)类似于
$(rm-rf$HOME)
的子字符串,它的行为会很糟糕。最好的做法是传递一个显式的argv数组,而不是一个字符串供shell解释,这样可以避免这些bug。我不能说我完全理解你的意思,但你的建议非常有效。谢谢。@user1634460--您试图以shell中的方式(例如,
${j}
)展开变量
j
。然而,在python中它不是这样工作的。您需要在字符串中插入特殊标记,告诉字符串如何替换为值。在这种情况下,
{0}
意味着用相应的
格式
方法调用中的第一个值替换该字符串。@Abuser3.145159它之所以有效,是因为您没有用足够有趣的输入来尝试它——如果字符串中有双引号,或者看起来像是变量解引用,或者(更糟糕!)类似于
$(rm-rf$HOME)
的子字符串,它的行为会很糟糕。最佳实践是传递一个显式的argv数组,而不是一个字符串供shell解释,这将避免这些错误。+1用于提供我懒得想出的
子流程
解决方案。。。(我记不起检查输出的名字了)@Charles Duffy谢谢。理论上我确实关心正确性,但实际上我只是想做一些相当卑微的事情。我花了好几年的时间用Matlab轻松地完成这些事情,但现在我开始尝试使用Python,因为有人认为这将是一个好主意….+1提供我懒得想出的
子流程
解决方案。。。(我记不起检查输出的名字了)@Charles Duffy谢谢。理论上我确实关心正确性,但实际上我只是想做一些相当卑微的事情。我花了好几年的时间用Matlab轻松地做这些事情,但现在我开始尝试使用Python,因为有人认为这是个好主意。。。。