0

I want to check if a string (user input) is in all files. 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')
Troll
  • 1,895
  • 3
  • 15
  • 34
TS Pham
  • 21
  • 4
  • 1
    You open every file in the working directory and check all of them, probably including your own script. On top of that, you open them once for each line in each file, so I expect your scripts seems rather slow - what's the point of the `for line ...` loop and the `open` command in the main section? You only need to open and loop over the file contents in the `check()` function? – Grismar Nov 01 '21 at 07:06
  • You are not returning anything, you are just printing the string `'True'` or `'False'`. – timgeb Nov 01 '21 at 07:07
  • @timgeb their function `check()` is actually returning the correct value, the part you are referring to is the main body of the script, not part of a function. – Grismar Nov 01 '21 at 07:07
  • @Grismar Yes. As I understand OP, all the code does is print `'True'`. – timgeb Nov 01 '21 at 07:08
  • Hey, this is almost word for word the same as https://stackoverflow.com/questions/4940032/how-to-search-for-a-string-in-text-files just with a different code snippet? – hostingutilities.com Nov 01 '21 at 08:29

2 Answers2

0

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
mozway
  • 194,879
  • 13
  • 39
  • 75
0

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') )
hostingutilities.com
  • 8,894
  • 3
  • 41
  • 51