我正在尝试在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表达式,但是我该如何解决呢?任何建议都表示赞赏。
答案 0 :(得分:3)
变量在python中不会像在bash中那样展开。你可能想要:
command = r'find . -type f -name "*{0}-xyz.stc" -printf "%f\n"'.format(j)
file_name = cmd.getoutput(command)
另请注意,commands
模块已弃用,而不是subprocess
。最后,应该指出,如果您将find
与os.walk
结合使用,则可以在 python 中编写此函数而不依赖glob.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))))
答案 1 :(得分:2)
file_name = cmd.getoutput('find . -type f -name "*%i-xyz.stc" -printf "%%f\n"' % (j))
答案 2 :(得分:1)
将字符串中的文件名传递给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分隔。否则,您无法区分名称中带换行符的文件与返回的两个文件之间的区别。
要了解其重要性,请考虑攻击者可以说服系统上运行的软件创建名称如此的文件的情况:
/your/top/dir/$'\n'/etc/passwd$'\n'/1-xyz.stc
如果您将find返回的每一行都视为文件名,您会认为/etc/passwd
是您返回值的一部分 - 如果您随后将此数据提供给用户,删除它等等,则会非常糟糕