Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

One-liner to get flat list of files from a list of possible directories?

Suppose we have a list of directories, some of which might not exist:

dirs = ['dir1','dir2','dir3']

For sake of argument only two exist and their content is:

dir1
  --file1a
  --file1b
dir2
  --file2a
  --file2b

What is the best one-liner to get a flat list of all the files? The closest I got was:

import os
files = [ os.listdir(x) for x in ['dir1','dir','dir3'] if os.path.isdir(x) ]

But that gives me a nested list:

[['file1a','file1b'],['file2a','file2b']]

What one-liner do I have to use instead, if I want that to be ['file1a', 'file1b', 'file2a', 'file2b']?

like image 253
con-f-use Avatar asked Mar 17 '23 22:03

con-f-use


2 Answers

You can chain the items into a single list:

from itertools import chain as ch


files = list(ch.from_iterable(os.listdir(x) for x in ['dir1', 'dir', 'dir3'] if os.path.isdir(x)))

shortest I can make it:

from itertools import chain as ch, ifilter as ifil, imap 
from os import path, listdir

files = list(ch.from_iterable(imap(listdir, ifil(path.isdir, ('dir1', 'dir', 'dir3')))))

If you just want to use the names then just iterate over the chain object.

like image 151
Padraic Cunningham Avatar answered Apr 26 '23 00:04

Padraic Cunningham


Not sure why a one-liner is what you want, but here:

files = [path for dir_lst in map(os.listdir, filter(os.path.isdir, ['dir1','dir','dir3'])) for path in dir_lst]

This filters the non-directories first (using filter), it then maps the os.listdir on what was left, and aggregates using two for loops.

like image 38
Reut Sharabani Avatar answered Apr 26 '23 02:04

Reut Sharabani