I am trying to execute the find command in a python script, using a for loop to pass a variable index determining the specific file name to find. I am using the following syntax, which in python returns an empty set, however works in the terminal:
for j in [1,2,3,5]:
file_name = cmd.getoutput('find . -type f -name "*${j}-xyz.stc" -printf "%f\n"')
Obviously, the variable is not being passed to the find expression in my python code, but how can I remedy that? Any suggestions are appreciated.
variables aren't expanded in python the same as they are in bash. You probably want:
command = r'find . -type f -name "*{0}-xyz.stc" -printf "%f\n"'.format(j)
file_name = cmd.getoutput(command)
Also note that the commands
module is deprecated in favor of subprocess
. Finally, it should probably be pointed out that you could write this function in python without relying on find
if you used os.walk
in conjunction with glob.glob
.
untested, but something like this should be close ...
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))))
file_name = cmd.getoutput('find . -type f -name "*%i-xyz.stc" -printf "%%f\n"' % (j))
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.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.