Home > Back-end >  How to search for a string in all files
How to search for a string in all files

Time:11-02

I want to check if a string (user input) is in all file. If it is, do X. If it's not, do Y. However, this code always returns True for some reason. Can anyone see what is wrong?

import os

text = 'T'

def check(filename, text):
    with open(filename) as dataf:
        return any(text in line for line in dataf)

for filename in os.listdir(os.getcwd()):
   with open(os.path.join(os.getcwd(), filename), 'r') as file_io: # open in readonly mode
       for line in file_io:
           if check(filename, text):
               print('True')
           else:
               print('False')
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

CodePudding user response:

You should apply your function to the files and check if all match.

if all(check(filename, text) for filename in os.listdir(os.getcwd())):
    # True
else:
    # at least one file is not matching

CodePudding user response:

You're rechecking if a file contains text over and over again as you iterate over each line in the file. You can fix this like so.

import os

text = 'T'

def check(filename, text):
    with open(filename) as dataf:
        return any(text in line for line in dataf)

for filename in os.listdir(os.getcwd()):
    if check(filename, text):
        print('True')
    else:
        print('False')

And that will now go through and print out true or false for each file depending on if it has text.

But you said that you want to check if a string is in all of the files. The all function can help us out with that. It will tell us if a list contains only True items.

import os

text = 'T'

def check(filename, text):
    with open(filename) as dataf:
        return any(text in line for line in dataf)

results = []
for filename in os.listdir(os.getcwd()):
    if check(filename, text):
        results.append(True)
    else:
        results.append(False)

print(all(results))

which can be made a little nicer. I've created a new function called main and shortened the way items were being appended to the results list.

import os

def check(filename, search_term):
    with open(filename) as dataf:
        return any(search_term in line for line in dataf)

def main(files, search_term):
    results = []
    for filename in files:
        results.append( check(filename, search_term) )
    return all(results)

print( main(os.listdir('.'), 'T') )

But we actually can turn that function into a simple one liner. os.listdir can also return directories, so we'll want to filter those out. And with some function names that better describe what we are doing we get

import os

def file_contains_string(file, search_term):
    with open(file) as dataf:
        return any(search_term in line for line in dataf)

def files_all_contain_string(files, search_term):
    return all( file_contains_string(f, search_term) for f in files if os.path.isfile(f) )

print( files_all_contain_string(os.listdir('.'), 'T') )
  • Related