Hi all,
I really tried to find a similar post that would help me sort my problem out but I didn’t succeed. The question is pretty straightforward - I want to process all of the text files within some (in this case) OneDrive directory mapped in Files.app. I know that because of sandboxing I couldn’t just hardcode the directory path in the script so I guess I would need to ask the user to choose the directory manually each time, but that’s fine. For now the biggest problem is that I have no idea how to set up the document picker dialog to let the user choose a directory instead of a file.
I would appreciate any help :)
Forum Archive
Listing files from given Files.app directory
@nizz71 How could you select a folder which has sub-folders?
Actually, tapping on a folder goes down...to display sub-folders or files.
@nizz71 It should be possible with ObjectiveC UIDocumentPickerViewController to allow multiple selection, select all files of the folder you want and get urls of all files of a folder....
My iPad is French speaking, "tout select" = "select all"

@cvp yeah that’s right and that’s exactly what I need to know - can I somehow specify a directory and “do stuff” with its content?
@nizz71 Tomorrow, I'll try...
There is a difference between knowing the Path and walking the Path. — The Matrix
from pathlib import Path
def visit(path: Path, depth: int = 0) -> None:
for item in path.iterdir():
s = f"{' ' * depth}{item.name}:"
if item.is_dir():
print(s)
visit(item, depth + 1)
else:
print(f"{s} {item.stat().st_size:,} bytes")
visit(Path("."))
@nizz71 Try this code
import ui
from objc_util import *
import urllib.parse
#===================== delegate of UIDocumentPickerViewController: begin
def documentPickerWasCancelled_(_self, _cmd, _controller):
#print('documentPickerWasCancelled_')
UIDocumentPickerViewController = ObjCInstance(_controller)
UIDocumentPickerViewController.uiview.close()
if UIDocumentPickerViewController.callback:
UIDocumentPickerViewController.callback('canceled')
UIDocumentPickerViewController.picked = 'canceled'
UIDocumentPickerViewController.done = True
def documentPicker_didPickDocumentsAtURLs_(_self, _cmd, _controller, _urls):
#print('documentPicker_didPickDocumentsAtURLs_')
UIDocumentPickerViewController = ObjCInstance(_controller)
UIDocumentPickerViewController.uiview.close()
urls = ObjCInstance(_urls)
if len(urls) == 1:
url = urllib.parse.unquote(str(urls[0]))
else:
url = []
for i in range(0,len(urls)):
url.append(urllib.parse.unquote(str(urls[i])))
if UIDocumentPickerViewController.callback:
UIDocumentPickerViewController.callback(url)
UIDocumentPickerViewController.picked = url
UIDocumentPickerViewController.done = True
methods = [documentPicker_didPickDocumentsAtURLs_,documentPickerWasCancelled_]
protocols = ['UIDocumentPickerDelegate']
try:
MyUIDocumentPickerViewControllerDelegate = ObjCClass('MyUIDocumentPickerViewControllerDelegate')
except:
MyUIDocumentPickerViewControllerDelegate = create_objc_class('MyUIDocumentPickerViewControllerDelegate', methods=methods, protocols=protocols)
#===================== delegate of UIDocumentPickerViewController: end
#def handler(_cmd):
# print('here')
#handler_block = ObjCBlock(handler, restype=None, argtypes=[c_void_p])
@on_main_thread
def MyPickDocument(w, h, mode='sheet', popover_location=None, callback=None, title=None, UTIarray=['public.item'], allowsMultipleSelection=False, PickerMode=1,tint_color=None):
# view needed for picker
uiview = ui.View()
uiview.frame = (0,0,w,h)
if mode == 'sheet':
uiview.present('sheet',hide_title_bar=True)
elif mode == 'popover':
if popover_location:
uiview.present('popover', hide_title_bar=True, popover_location=popover_location)
else:
return
else:
return
UIDocumentPickerMode = PickerMode
# 1 = UIDocumentPickerMode.open
# this mode allows a search field
# and url in delegate is the original one
# 0 = UIDocumentPickerMode.import
# url is url of a copy
UIDocumentPickerViewController = ObjCClass('UIDocumentPickerViewController').alloc().initWithDocumentTypes_inMode_(UTIarray,UIDocumentPickerMode)
#print(dir(UIDocumentPickerViewController))
objc_uiview = ObjCInstance(uiview)
SUIViewController = ObjCClass('SUIViewController')
vc = SUIViewController.viewControllerForView_(objc_uiview)
if title:
l = ui.Label()
wb = 80
wl = uiview.width - 2*wb # title width
#l.border_width = 1 # for tests only
l.text = title
l.alignment = ui.ALIGN_CENTER
# find greatest font size allowing to display title between buttons
fs = 16
while True:
wt,ht = ui.measure_string(title,font=('Menlo',fs))
if wt <= wl:
break
fs = fs - 1
l.frame = (wb,0,wl,fs)
l.text_color = 'green'
UIDocumentPickerViewController.view().addSubview_(ObjCInstance(l))
UIDocumentPickerViewController.setModalPresentationStyle_(3) #currentContext
# Use new delegate class:
delegate = MyUIDocumentPickerViewControllerDelegate.alloc().init()
UIDocumentPickerViewController.delegate = delegate
UIDocumentPickerViewController.callback = callback # used by delegate
UIDocumentPickerViewController.uiview = uiview # used by delegate
UIDocumentPickerViewController.done = False
UIDocumentPickerViewController.allowsMultipleSelection = allowsMultipleSelection
vc.presentViewController_animated_completion_(UIDocumentPickerViewController, True, None)#handler_block)
if tint_color != None:
r,g,b = tint_color
UIDocumentPickerViewController.view().setTintColor_(ObjCClass('UIColor').colorWithRed_green_blue_alpha_(r,g,b,1.0))
return UIDocumentPickerViewController
def main():
# demo code
def callback(param):
# you could check if file save at hoped place...
print(param)
MyPickDocument(600,500, callback=callback, title='test', allowsMultipleSelection=True)
#MyPickDocument(600,500, mode ='popover', popover_location=(mv.width-40,60))
if __name__ == '__main__':
main()
It allows even to select a folder (I didn't know 😀)

@cvp awesome code, works like a charm 🙂 now I can choose a directory and get its URL, but.. I still can’t get it to list its content. I feel like I should use FileManager class for it (part of Foundation). I have completely no ObjC background, so I’m a little Daredevilling here, and here’s what I came up with in order to list the content of the chosen directory:
fileManager = ObjCClass("NSFileManager").alloc().init()
fileManager.contentsOfDirectoryAtURL_includingPropertiesForKeys_options_error_(param,[],4,None)
where param is the URL of the directory I got from your script. When I run the script it just crashes and Pythonista shuts down. Is python’s None type the equivalent of ObjC nil? I didn’t know how to pass enumeration options as the third parameter so I just put the default value there (based on the documentation). Could you help me with that as well?
print(os.listdir(pathname))
Sorry, if you are starting with an nsurl, then you would use nsurl.path() iirc
@nizz71 If instead of selecting a directory, you tap it and select all files in this directory, you will get an array with the urls of all files of this folder
['file:///private/var/mobile/Library/Mobile Documents/com~apple~CloudDocs/Mes donnees/Pythonista/Backup/Examples/Games/BrickBreaker.py', 'file:///private/var/mobile/Library/Mobile Documents/com~apple~CloudDocs/Mes donnees/Pythonista/Backup/Examples/Games/filters.fsh', 'file:///private/var/mobile/Library/Mobile Documents/com~apple~CloudDocs/Mes donnees/Pythonista/Backup/Examples/Games/game_levels.py', 'file:///private/var/mobile/Library/Mobile Documents/com~apple~CloudDocs/Mes donnees/Pythonista/Backup/Examples/Games/game_menu.py', 'file:///private/var/mobile/Library/Mobile Documents/com~apple~CloudDocs/Mes donnees/Pythonista/Backup/Examples/Games/Match3.py']

@nizz71 Yes None = nil
It does not crash with
x = fileManager.contentsOfDirectoryAtPath_error_(param,None)
But returns None, thus that does not help 😢