Я должен сохранить весь каталог, который содержит файлы в определенном подкаталоге, но удалить оставляют все каталоги, в которых подкаталог пуст.
Чтобы быть более конкретной вот, структура:
A
|
|--------312311
| |
| |----Recording
| |----a.txt
| |----b.txt
|
|
|--------453453
| |----Recording
| |
| |-------a.mp3
| |----a.txt
| |----b.txt
|
|
|--------566532
| |----Recording
| |----a.txt
| |----b.txt
Подкаталоги могут или не могут содержать файл. Таким образом, я должен удалить целый каталог как '312 311' и '566532', и только '453 453' нужно оставить со всеми данными в нем, потому что он имеет файл в папке 'Recording', которая является определенным каталогом для меня.
Я видел много сообщений, но это связывается со многими определенными именами файлов. Любая справка будет очень цениться, как я должен делать много раз через неделю.
Сценарий ниже сделает точно, как Вы описываете, он:
Взгляды в каждой из папок для папки под названием "Запись"
В изображении:
A
|
|--------123456
| |
| |----Recording
| |----a.txt
| |----b.txt
|
|
|--------635623
| |----Recording
| |
| |-------a.mp3
| |----a.txt
| |----b.txt
|
|
|--------123456
| |----Recording
| |----a.txt
| |----b.txt
|
|--------Monkey.txt
приведет к:
A
|
|
|--------635623
| |----Recording
| |
| |-------a.mp3
| |----a.txt
| |----b.txt
|
|
|--------Monkey.txt
#!/usr/bin/env python3
import os
import sys
import shutil
dr = sys.argv[1]
def path(*args):
return os.path.join(*args)
for d in os.listdir(dr):
try:
if not os.listdir(path(dr, d, "Recording")):
shutil.rmtree(path(dr,d))
except FileNotFoundError:
shutil.rmtree(path(dr,d))
except NotADirectoryError:
pass
delete_empty.py
Выполните его с (полный!) каталог (содержащий Ваш subdirs, в Вашем примере) как аргумент командой:
python3 /path/to/delete_empty.py /path/to/directory
Именно.
Питание содержания папки "A" к сценарию,
os.listdir(dr)
перечислит его подкаталоги (и файлы). Затем:
if not os.listdir(path(dr, d, "Recording"))
попытается перечислить содержание каждой из (sub) папок, которые повысят ошибку, если объект будет файлом:
except NotADirectoryError
pass
или если папка "Recording" не существует вообще:
FileNotFoundError
shutil.rmtree(path(dr,d))
Если папка "Recording" существует и пуста, превосходящая папка удалена:
if not os.listdir(path(dr, d, "Recording")):
shutil.rmtree(path(dr,d))
Кроме того, согласно просьбе в комментариях, версия, которая проверит на несколько subdirs (имена).
В случае, если каталог содержит любой из перечисленных (не-пустой) subdirs, каталог сохранен. Еще это будет удалено.
delete_empty.py
Выполните его с (полный!) каталог (содержащий Ваш subdirs, в Вашем примере) и названия subdirs как аргументы командой:
python3 /path/to/delete_empty.py /path/to/directory <subdir1> <subdir2> <subdir3>
Именно.
#!/usr/bin/env python3
import shutil
import os
import sys
dr = sys.argv[1]; matches = sys.argv[2:]
def path(*args):
return os.path.join(*args)
for d in os.listdir(dr):
# delete directory *unless* either one of the listed subdirs has files
keep = False
# check for each of the listed subdirs(names)
for name in matches:
try:
if os.listdir(path(dr, d, name)):
keep = True
break
except NotADirectoryError:
# if the item is not a dir, no use for other names to check
keep = True
break
except FileNotFoundError:
# if the name (subdir) does not exist, check for the next
pass
if not keep:
# if there is no reason to keep --> delete
shutil.rmtree(path(dr,d))
Первый показ на тестовом каталоге для проверки это делает точно, что Вы хотите.
Используя find
и xargs
:
find A -type d -name 'Recording' -empty -printf '%h\0' | xargs -0 echo rm -rf
(удалите echo
, как только вам будет удобно, чтобы он идентифицировал правильные каталоги). Часть printf '%h\0
печатает (нулевой завершенный) родительский каталог - из man find
:
%h Leading directories of file's name (all but the last ele‐
ment). If the file name contains no slashes (since it is
in the current directory) the %h specifier expands to
".".
Пример: дано
$ tree A
A
├── 312311
│ ├── a.txt
│ ├── b.txt
│ └── Recording
├── 453453
│ ├── a.txt
│ ├── b.txt
│ └── Recording
│ └── a.mp3
└── 566532
├── a.txt
├── b.txt
└── Recording
6 directories, 7 files
, затем
$ find A -type d -name 'Recording' -empty -printf '%h\0' | xargs -0 rm -rf
$
$ tree A
A
└── 453453
├── a.txt
├── b.txt
└── Recording
└── a.mp3
2 directories, 3 files
Вот более простое решение для удара:
for d in */; do rmdir "$d/Recording" && rm -r "$d"; done
Это работает потому что rmdir
перестанет работать, если каталог не будет пуст, и &&
предотвратит rm -r
от того, чтобы быть выполняемым, если rmdir
успешно выполняется. Шарик */
удостоверяется, что Вы только работаете над каталогами, таким образом, другие файлы не будут затронуты.