os.listdir()
, as its name implies, returns a list of all occupants of the given directory, including both files and directories (and, if you're on Unix/Linux, other stuff like symlinks and devices and whatnot). You are then blindly trying to open()
each item in the list and print()
its contents. Unfortunately, open()
only works on file-like objects, and specifically does not work on directories, hence Errno 13, Permission Denied.
An alternative is to use os.scandir()
, which works a little bit differently. Instead of returning a flat list that you can read immediately, os.scandir()
returns a generator which essentially gives you objects as you ask for them, instead of giving them all to you at once. In fact, the following code adapted from the docs is a good starting place for what you need:
for entry in os.scandir(path):
if entry.is_file():
print(entry.name)
os.scandir()
is returning DirEntry
objects. Simply use os.path.join()
to create a full pathname out of the path
argument you pass to os.listdir()
in your original code, and entry.name
from the code above, and then, using the with
context manager, open()
the file and display its contents:
for entry in os.scandir(path):
if entry.is_file():
with open(os.path.join(path, entry), "r") as f:
for line in f:
print(line)
One of the advantages of using with
is that you don't have to remember to close the file handle that is assigned when you use something like this:
f = open("myfile.txt, "r")
# do stuff with f
...
f.close()
Otherwise, you have a dangling file handle that could potentially cause problems, depending on how many there are and what you've done with them. It's just a good practice to close()
what you open()
. With with
, you don't have to worry about it - the file handle is closed as soon as you exit the block.