How to append subdirectories to a list in python - python

I would like to know how I can only append sub-directories of a given directory to a list in Python.
Something like this is not what I'm searching for as it outputs the files:
filelist = []
for root, dirs, files in os.walk(job['config']['output_dir']):
for file in files:
# append the file name to the list
filelist.append(os.path.join(root, file))
# print all the file names
for name in filelist:
print(name)

Just use the dirs variable instead the files variable, like this:
dirs_list = []
for root, dirs, files in os.walk('test'):
for dir in dirs:
dirs_list.append(os.path.join(root, dir))
print(dirs_list)

Related

Paython script not finding files

I have following script which is supposed to list all picture etc from my disk drives, but it failes to find any file. Any Idea what I may be doing wrong. I am doing in PyCharm environment:
files = []
for root, dirs, files in os.walk("."):
for file in files:
if file.endswith((".jpg", ".jpeg", ".mp3", ".mp4")):
files.append(os.path.join(root, file))
# Sort the files by their current folder name
files.sort(key=lambda x: os.path.dirname(x))
# Display a list of the files
for file in files:
print(file)
Your for-loop will never end as you add the found file name into files which you are looping through. Use another variable to store the list.
This works fine:
import os
results = []
for root, dirs, files in os.walk("."):
print(f"Got: {len(results)} files, current dir: {root}")
for file in files:
if file.endswith((".jpg", ".jpeg", ".mp3", ".mp4")):
results.append(os.path.join(root, file))
# Sort the files by their current folder name
results.sort(key=lambda x: os.path.dirname(x))
# Display a list of the files
for file in results:
print(file)

Python recursively traverse through all subdirs and write the filenames to output file

I want to recursively traverse through all subdirs in a root folder and write all filenames to an output file. Then in each subdir, create a new output file inside the subdir and recursively traverse through its subdirs and append the filename to the new output file.
So in the example below, under the Music folder it should create a Music.m3u8 file and recursively traverse all subdirs and add all filenames in each subdir to the Music.m3u8 file. Then in Rock folder, create a Rock.m3u8 file and recursively traverse all subdirs within the Rock folder and add all filenames in each subdirs in Rock.m3u8. Finally in each Album folder, create Album1.m3u8, Album2.m3u8, etc with the filenames in its folder. How can I do this in python3.6?
Music
....Rock
........Album1
........Album2
....Hip-Hop
........Album3
........Album4
This is what I have but only adds the filenames of each folder to an output file but doesn't recursively adds to the root output file.
import os
rootdir = '/Users/bayman/Music'
ext = [".mp3", ".flac"]
for root, dirs, files in os.walk(rootdir):
path = root.split(os.sep)
if any(file.endswith(tuple(ext)) for file in files):
m3ufile = str(os.path.basename(root))+'.m3u8'
list_file_path = os.path.join(root, m3ufile)
with open(list_file_path, 'w') as list_file:
list_file.write("#EXTM3U\n")
for file in sorted(files):
if file.endswith(tuple(ext)):
list_file.write(file + '\n')
You're doing with open(list_file_path, 'w') as list_file: each time through the outer loop. But you're not creating, or writing to, any top-level file, so of course you don't get one. If you want one, you have to explicitly create it. For example:
rootdir = '/Users/bayman/Music'
ext = [".mp3", ".flac"]
with open('root.m3u', 'w') as root_file:
root_file.write("#EXTM3U\n")
for root, dirs, files in os.walk(rootdir):
path = root.split(os.sep)
if any(file.endswith(tuple(ext)) for file in files):
m3ufile = str(os.path.basename(root))+'.m3u8'
list_file_path = os.path.join(root, m3ufile)
with open(list_file_path, 'w') as list_file:
list_file.write("#EXTM3U\n")
for file in sorted(files):
if file.endswith(tuple(ext)):
root_file.write(os.path.join(root, file) + '\n')
list_file.write(file + '\n')
(I'm just guessing at what you actually want in that root file here; you presumably know the answer to that and don't have to guess…)

Fastest way to search for a list of files in directory

Given a list of file names, I want to create the full path for these files if they exist in a given directory or it's sub-directories. Right now I use this code
def construct_path(file_list, directory):
file_path_list = []
for name in file_list:
for dir, subdir, filenames in os.walk(directory):
if name in filenames:
file_path_list.append(os.path.join(dir, name))
return file_path_list
So here the directory is being crawled for each file in the list. Is there a faster/better way to do it?
You can remove the loop over the file_list and remove found files from this list, so you can return the results once you have found all your files:
def construct_path(file_list, directory):
file_path_list = []
for dir, subdir, files in os.walk(directory):
for name in files:
if name in file_list:
file_path_list.append(os.path.join(dir, name))
file_list.remove(name)
if (len(file_list)==0): return file_path_list
return file_path_list

searching for a filename with extension and printing its relative path

I have the below code to print the filename which is find criteria with file extension *.org. How could I print the relative path of the file found. Thanks in advance
def get_filelist() :
directory = "\\\\networkpath\\123\\abc\\"
filelist = []
for root, dirs, files in os.walk(directory):
for file in files:
if file.endswith('Org'):
print(str(dirs) +"\\" + str(file)) #prints empty list [] followed by filename
filelist.append(os.path.splitext(file)[0])
return (filelist)
Please see me as novice in python
files and dirs list the children of root. dirs thus lists siblings of file. You want to print this instead:
print(os.path.relpath(os.path.join(root, file)))
you need to use os.path.join:
def get_filelist() :
directory = "\\\\networkpath\\123\\abc\\"
filelist = []
for root, dirs, files in os.walk(directory):
for file in files:
if file.endswith('org'): # here 'org' will be in small letter
print(os.path.join(root,file))
filelist.append(os.path.join(root,file))
return filelist

Dynamic if statement in dictionary comprehension

I am using a dictionary comprehension to get a dictionary of key value pairs where the key is the name of an mp3 file and the value is the path to the file.
I do:
for root, dirs, files in os.walk(rootDir, topdown='true'):
source_files = {filename:root for filename in files if os.path.splitext(filename)[1].lower() == '.mp3'}
# more code
# ...
# ...
I do more logic with the source files in the more code part. Now, I want to repeat this logic for any pictures (i.e. .gif, .jpeg etc)
So I could do:
for root, dirs, files in os.walk(rootDir, topdown='true'):
source_files = {filename:root for filename in files if os.path.splitext(filename)[1].lower() == '.jpeg' or os.path.splitext(filename)[1].lower() == '.gif'}
and then wrap the more code part into a function and call it for the picture files. However, I am wondering could I just make the if expression dynamic in the dictionary comprehension and then just pass in one if expression for music files and another if expression for the picture files?
I think you are looking for the fnmatch.fnmatch function instead, or even fnmatch.filter()
from fnmatch import filter
for root, dirs, files in os.walk(rootDir):
source_files = {filename: root for filename in filter(files, '*.jpg')}
But if you need to match multiple extensions, it's much easier to use str.endswith():
for root, dirs, files in os.walk(rootDir):
source_files = {filename: root for filename in files if filename.endswith(('.jpg', '.png', '.gif'))}
Using .endswith() you can then use any string or tuple of extensions:
mp3s = '.mp3'
images = ('.jpg', '.png', '.gif')
then use:
extensions = images
for root, dirs, files in os.walk(rootDir):
source_files = {filename: root for filename in files if filename.endswith(extensions)}
I'm not sure why you are using a dict comprehension here; each iteration of the loop, root will be constant. You may as well do:
for root, dirs, files in os.walk(rootDir):
source_files = dict.fromkeys(filter(files, '*.jpg'), root)
or use
for root, dirs, files in os.walk(rootDir):
source_files = dict.fromkeys([f for f in files if f.endswith(extensions)], root)
If you wanted to create a dictionary of all files in a nested directory structure, you'll need to move the dict comprehension out and integrate the os.walk() call in the dict comprehension instead:
source_files = {filename: root
for root, dirs, files in os.walk(rootDir)
for filename in files if f.endswith(extensions)}
I removed all the topdown='true' lines; the default is topdown=True anyway (note: python booleans are True and False, not strings. It happened to work because 'true' as a string is 'truthy', it's considered True in a boolean context because it is non-empty).
Does this:
def a_func(extension):
# some code
for root, dirs, files in os.walk(rootDir, topdown='true'):
source_files = {filename:root for filename in files if os.path.splitext(filename)[1].lower() == extension}
# more code
# ...
# ...
fit your needs?

Categories

Resources