#python #python-3.x #recursion
Вопрос:
Я написал эту простую функцию, которая рекурсивно перечисляет содержимое каталога и его подкаталогов, она возвращает словарь только с одним ключом, корневым ключом, который является введенным путем, значение ключа представляет собой список содержимого, если содержимое представляет собой файл, соответствующий элемент str
содержит имя файла с расширением;
В противном случае, если содержимое представляет собой папку, соответствующий элемент dict
структурирован с использованием формата, аналогичного указанному выше, разница в том, что ключом является путь относительно введенного пути, а не абсолютный путь.
Код:
from pathlib import Path def recur_dir(path, first=True, root=''): if first: root = str(path).replace('\', '/') if not root.endswith('/'): root = '/' result = {root: []} entries = result[root] else: entries = [] result = entries for entry in Path(path).glob('*'): if entry.is_dir(): entry = {str(entry).replace('\', '/').replace(root, ''): recur_dir(entry, False, root)} else: entry = entry.name entries.append(entry) return result
Пример:
In [45]: import json; print(json.dumps(recur_dir('C:/Program Files (x86)/ExpressVPN'), indent=4)) { "C:/Program Files (x86)/ExpressVPN/": [ { "bootstrap": [ { "bootstrap/amd64": [ "nssm.exe" ] } ] }, { "expressvpn-ui": [ { "expressvpn-ui/Assets": [ { "expressvpn-ui/Assets/en-US": [ "150x150Logo.scale-100.png", "150x150Logo.scale-125.png", "150x150Logo.scale-150.png", "150x150Logo.scale-200.png", "150x150Logo.scale-400.png", "44x44Logo.scale-100.png", "44x44Logo.scale-125.png", "44x44Logo.scale-150.png", "44x44Logo.scale-200.png", "44x44Logo.scale-400.png", "70x70Logo.scale-100.png", "70x70Logo.scale-125.png", "70x70Logo.scale-150.png", "70x70Logo.scale-200.png", "70x70Logo.scale-400.png" ] } ] }, "AustinHarris.JsonRpc.dll", "Caliburn.Micro.dll", "Caliburn.Micro.Platform.dll", "CommandLine.dll", "Common.Logging.Core.dll", "Common.Logging.dll", "Common.Logging.Log4Net1213.dll", "ExpressVPN-Installer.exe", "ExpressVPN-Installer.exe.config", "ExpressVPN.Client.Engine.dll", "ExpressVPN.Client.EngineProxy.dll", "ExpressVPN.Client.Installer.dll", "ExpressVPN.Client.Utils.dll", "ExpressVpn.Client.Utils.NamedPipes.dll", "ExpressVPN.Client.Windows.dll", "ExpressVPN.exe", "ExpressVPN.exe.config", "ExpressVPN.Utils.dll", "ExpressVpn.Utils.Wmi.dll", "ExpressVPN.VisualElementsManifest.xml", "ExpressVPNNotificationService.exe", "ExpressVPNNotificationService.exe.config", "ExpressVPNNotificationServiceStarter.exe", "Hardcodet.Wpf.TaskbarNotification.dll", "HtmlAgilityPack.dll", "IconLib.dll", "log4net.dll", "ManagedWifi.dll", "Microsoft.Toolkit.Uwp.Notifications.dll", "MissingLinq.Linq2Management.dll", "Newtonsoft.Json.dll", "Resources.pri", "RestSharp.dll", "Sentry.dll", "Sentry.PlatformAbstractions.dll", "Sentry.Protocol.dll", "System.Management.Automation.dll", "System.Reactive.Core.dll", "System.Reactive.Interfaces.dll", "System.Reactive.Linq.dll", "System.Reactive.Windows.Threading.dll", "System.Runtime.InteropServices.RuntimeInformation.dll", "System.ValueTuple.dll", "System.Windows.Interactivity.dll" ] }, { "expressvpnd": [ { "expressvpnd/.config": [ { "expressvpnd/.config/expressvpn": [ "browser_helper" ] } ] }, "com.expressvpn.helper.firefox.json", "com.expressvpn.helper.json", "expressvpn-browser-helper.exe", "expressvpnd.exe", "libxvclient.dll", "lightway.exe", { "expressvpnd/windows": [ "ExpressVPN.FilterManager.dll", "ExpressVPN.NetworkUtils.dll", "ExpressVPN.SplitTunnel.dll", "libcrypto-1_1-x64.dll", "liblzo2-2.dll", "libpkcs11-helper-1.dll", "libssl-1_1-x64.dll", "notices.rtf", "openvpn.exe", { "expressvpnd/windows/rasutility": [ "Common.Logging.Core.dll", "Common.Logging.dll", "Common.Logging.Log4Net1213.dll", "DotRas.dll", "ExpressVPN.Utils.dll", "log4net.dll", "ManagedWifi.dll", "Newtonsoft.Json.dll", "RasUtility.exe", "RasUtility.exe.config", "Sentry.dll", "Sentry.PlatformAbstractions.dll", "Sentry.Protocol.dll", "System.Management.Automation.dll", "System.Reactive.Core.dll", "System.Reactive.Interfaces.dll", "System.Reactive.Linq.dll", "System.Runtime.InteropServices.RuntimeInformation.dll", "System.ValueTuple.dll" ] }, { "expressvpnd/windows/xvutil": [ "CommandLine.dll", "Common.Logging.Core.dll", "Common.Logging.dll", "Common.Logging.Log4Net1213.dll", "ExpressVPN.EngineUtils.dll", "ExpressVPN.Utils.dll", "ExpressVpn.Utils.Wmi.dll", "log4net.dll", "ManagedWifi.dll", "MissingLinq.Linq2Management.dll", "Newtonsoft.Json.dll", "Sentry.dll", "Sentry.PlatformAbstractions.dll", "Sentry.Protocol.dll", "System.Management.Automation.dll", "System.Reactive.Core.dll", "System.Reactive.Interfaces.dll", "System.Reactive.Linq.dll", "System.Runtime.InteropServices.RuntimeInformation.dll", "System.ValueTuple.dll", "XvUtil.exe", "XvUtil.exe.config" ] } ] } ] }, { "splittunnel": [ "expressvpndriverinstaller.exe", "expressvpnsplittunnel.cat", "expressvpnsplittunnel.inf", "expressvpnsplittunnel.sys" ] }, { "tap": [ { "tap/driver": [ { "tap/driver/amd64": [ "HWCertReport_1152921505690468143.html", "OemVista.inf", "tapexpressvpn.cat", "tapexpressvpn.sys" ] } ] }, { "tap/tapinstall": [ { "tap/tapinstall/amd64": [ "tapinstall.exe" ] } ] } ] }, { "wintun": [ { "wintun/driver": [ { "wintun/driver/amd64": [ "expressvpn-wintun.cat", "expressvpn-wintun.inf", "expressvpn-wintun.sys", "HWCertReport_1152921505692733217.html" ] } ] } ] } ] }
I would like to how to recursively pop elements that represent empty folders and flatten directories that contain only one subdirectory.
As you can see, if the content is a folder it is represented as a dict
, with its path as key and the list of its contents as the value, and if the folder is empty the value is an empty list
.
And if the content is a folder the value is a list of only one dict
element …
In short I want it to become this:
{ "C:/Program Files (x86)/ExpressVPN/": [ { "bootstrap/amd64": [ "nssm.exe" ] }, { "expressvpn-ui": [ { "expressvpn-ui/Assets/en-US": [ "150x150Logo.scale-100.png", "150x150Logo.scale-125.png", "150x150Logo.scale-150.png", "150x150Logo.scale-200.png", "150x150Logo.scale-400.png", "44x44Logo.scale-100.png", "44x44Logo.scale-125.png", "44x44Logo.scale-150.png", "44x44Logo.scale-200.png", "44x44Logo.scale-400.png", "70x70Logo.scale-100.png", "70x70Logo.scale-125.png", "70x70Logo.scale-150.png", "70x70Logo.scale-200.png", "70x70Logo.scale-400.png" ] }, "AustinHarris.JsonRpc.dll", "Caliburn.Micro.dll", "Caliburn.Micro.Platform.dll", "CommandLine.dll", "Common.Logging.Core.dll", "Common.Logging.dll", "Common.Logging.Log4Net1213.dll", "ExpressVPN-Installer.exe", "ExpressVPN-Installer.exe.config", "ExpressVPN.Client.Engine.dll", "ExpressVPN.Client.EngineProxy.dll", "ExpressVPN.Client.Installer.dll", "ExpressVPN.Client.Utils.dll", "ExpressVpn.Client.Utils.NamedPipes.dll", "ExpressVPN.Client.Windows.dll", "ExpressVPN.exe", "ExpressVPN.exe.config", "ExpressVPN.Utils.dll", "ExpressVpn.Utils.Wmi.dll", "ExpressVPN.VisualElementsManifest.xml", "ExpressVPNNotificationService.exe", "ExpressVPNNotificationService.exe.config", "ExpressVPNNotificationServiceStarter.exe", "Hardcodet.Wpf.TaskbarNotification.dll", "HtmlAgilityPack.dll", "IconLib.dll", "log4net.dll", "ManagedWifi.dll", "Microsoft.Toolkit.Uwp.Notifications.dll", "MissingLinq.Linq2Management.dll", "Newtonsoft.Json.dll", "Resources.pri", "RestSharp.dll", "Sentry.dll", "Sentry.PlatformAbstractions.dll", "Sentry.Protocol.dll", "System.Management.Automation.dll", "System.Reactive.Core.dll", "System.Reactive.Interfaces.dll", "System.Reactive.Linq.dll", "System.Reactive.Windows.Threading.dll", "System.Runtime.InteropServices.RuntimeInformation.dll", "System.ValueTuple.dll", "System.Windows.Interactivity.dll" ] }, { "expressvpnd": [ { "expressvpnd/.config/expressvpn": [ "browser_helper" ] }, "com.expressvpn.helper.firefox.json", "com.expressvpn.helper.json", "expressvpn-browser-helper.exe", "expressvpnd.exe", "libxvclient.dll", "lightway.exe", { "expressvpnd/windows": [ "ExpressVPN.FilterManager.dll", "ExpressVPN.NetworkUtils.dll", "ExpressVPN.SplitTunnel.dll", "libcrypto-1_1-x64.dll", "liblzo2-2.dll", "libpkcs11-helper-1.dll", "libssl-1_1-x64.dll", "notices.rtf", "openvpn.exe", { "expressvpnd/windows/rasutility": [ "Common.Logging.Core.dll", "Common.Logging.dll", "Common.Logging.Log4Net1213.dll", "DotRas.dll", "ExpressVPN.Utils.dll", "log4net.dll", "ManagedWifi.dll", "Newtonsoft.Json.dll", "RasUtility.exe", "RasUtility.exe.config", "Sentry.dll", "Sentry.PlatformAbstractions.dll", "Sentry.Protocol.dll", "System.Management.Automation.dll", "System.Reactive.Core.dll", "System.Reactive.Interfaces.dll", "System.Reactive.Linq.dll", "System.Runtime.InteropServices.RuntimeInformation.dll", "System.ValueTuple.dll" ] }, { "expressvpnd/windows/xvutil": [ "CommandLine.dll", "Common.Logging.Core.dll", "Common.Logging.dll", "Common.Logging.Log4Net1213.dll", "ExpressVPN.EngineUtils.dll", "ExpressVPN.Utils.dll", "ExpressVpn.Utils.Wmi.dll", "log4net.dll", "ManagedWifi.dll", "MissingLinq.Linq2Management.dll", "Newtonsoft.Json.dll", "Sentry.dll", "Sentry.PlatformAbstractions.dll", "Sentry.Protocol.dll", "System.Management.Automation.dll", "System.Reactive.Core.dll", "System.Reactive.Interfaces.dll", "System.Reactive.Linq.dll", "System.Runtime.InteropServices.RuntimeInformation.dll", "System.ValueTuple.dll", "XvUtil.exe", "XvUtil.exe.config" ] } ] } ] }, { "splittunnel": [ "expressvpndriverinstaller.exe", "expressvpnsplittunnel.cat", "expressvpnsplittunnel.inf", "expressvpnsplittunnel.sys" ] }, { "tap": [ { "tap/driver/amd64": [ "HWCertReport_1152921505690468143.html", "OemVista.inf", "tapexpressvpn.cat", "tapexpressvpn.sys" ] }, { "tap/tapinstall/amd64": [ "tapinstall.exe" ] } ] }, { "wintun/driver/amd64": [ "expressvpn-wintun.cat", "expressvpn-wintun.inf", "expressvpn-wintun.sys", "HWCertReport_1152921505692733217.html" ] } ] }
Как это сделать?