Распечатать, какая подпапка пуста во всех папках, содержащих одну и ту же подпапку?

1

У меня есть папка A, как это:

A>>(B,C,D)(subfolders)>>both B,C and D have folders 1,2,3 each.

в этом случае подпапка "3" из B, C и D оказывается пустой.

Как вы проверяете и печатаете, какая папка бывает пустой во всех папках, например, чтобы выполнить поиск и распечатать номер "3", поскольку это единственная вложенная папка, которая пуста во всех папках B, C и D?

Код, который я пробовал:

for i in glob.iglob('**/Desktop/A/**' ,recursive = True):
    if not os.listdir(i):
        print(f'{i} is empty everywhere' + '\n')

который не работает.

Все папки имеют одинаковые подпапки (имя), но некоторые из них пусты. Мне нужно найти пустоты во всех этих папках и распечатать их.

  • 1
    Для пояснения: все ваши каталоги (в данном случае A, B, C ) имеют один и тот же подкаталог, и вы хотите напечатать имя только одного подкаталога, если он пуст во всех трех каталогах? Так что, если папка 3 будет пустой в A и B но не в C , вы не хотите ее печатать?
  • 0
    Можно ли жестко запрограммировать структуру папок? Другими словами, это все еще должно работать, если вы добавляете новую папку «E» или новую подпапку «4»?
Показать ещё 2 комментария
Теги:
glob

2 ответа

1
Лучший ответ

Нам нужны две функции из модуля os

from os import walk
from os.path import join

Нам нужна начальная точка

dir = '/your/top/directory'

walk возвращает генератор, итерацию на нем на каждом шаге у нас есть путь к текущему каталогу, список каталогов и список файлов, но мы не хотим итерации и интересуемся только списком каталогов в текущем каталоге, следовательно

dirs_l1 = next(walk(dir))[1]

обратите внимание, что, имея дело с генератором, вышесказанное не слишком расточительно...

Теперь у нас есть внутренний цикл в подкаталогах уровня 1 (l1 sd, sd, содержащийся в корне), чтобы создать список наборов каталогов уровня 2, который будет распакован и передан в set.intersection, так что в dirs_l2 мы в конце концов, имеет набор всех каталогов уровня 2, которые присутствуют в каждом каталоге уровня 1

dirs_l2 = set.intersection(*[set(next(walk(join(dir, d)))[1]) for d in dirs_l1])

Мы делаем цикл на этих внутренних каталогах, присутствующих в каждом l1 sd, и используя all встроенные, мы проверяем, что для каждого l1 sd все l2 sd пустые, в этом случае мы печатаем имя подкаталога l2, которое всегда пустое

for d2 in dirs_l2:
    if all(next(walk(join(dir, d1, d2)))[1:] == ([],[]) for d1 in dirs_l1):
        print(d2)

Пример

$ cat A.py
from os import walk
from os.path import join
dir = './A'
dirs_l1 = next(walk(dir))[1]
dirs_l2 = set.intersection(*[set(next(walk(join(dir, d)))[1]) for d in dirs_l1])
for d2 in dirs_l2:
    if all(next(walk(join(dir, d1, d2)))[1:] == ([], []) for d1 in dirs_l1): print(d2)
$ tree A
A
├── A
│   ├── 1
│   │   └── a
│   ├── 2
│   │   └── b
│   └── 3
├── B
│   ├── 1
│   │   └── a
│   ├── 2
│   │   └── b
│   └── 3
├── C
│   ├── 1
│   │   └── a
│   ├── 2
│   │   └── b
│   └── 3
└── D
    ├── 1
    │   └── a
    ├── 2
    │   └── b
    └── 3
$ python A.py 
3
$ 
  • 0
    Хороший ответ, проголосовал.
0

Самое простое решение, о котором можно подумать, - это использовать карту, где ключи - это имена папок, а значения могут быть логическими. True если пусто везде, False otherwhise. Значение по умолчанию будет True. Поэтому я бы использовал:

all_empty_map = {}
for i in glob.iglob('**/Desktop/A**', recursive=True):
    cur_dir = os.path.basename(i)
    all_empty_map[cur_dir] = all_empty_map.get(cur_dir, True) and not os.listdir(i)

for cur_dir, isempty in all_empty_map.items():
    if isempty:
        print cur_dir

Конечно, могут быть вещи, которые могут быть оптимизированы в коде.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню