Files and folders
This is where MaSH starts to earn its keep. Everything in Foldr is a file or a folder on a share, and mash.files lets a script work with them whatever storage sits behind the share: SMB, S3, SharePoint, OneDrive and the rest.
The examples in this chapter and the next need a real share, so they aren’t run automatically. Each one is marked, and each one has been checked to be valid MaSH. To try them, swap in the name of a share of your own and use a test folder.
Getting a file
Section titled “Getting a file”mash.files.get(share, path) returns a File object. The share is its name or id. The path starts from the share’s root and uses /:
set invoice to mash.files.get("Finance", "Invoices/2026/INV-2041.pdf")printline invoice.nameprintline invoice.sizeinvoice = mash.files.get("Finance", "Invoices/2026/INV-2041.pdf")printline(invoice.name)printline(invoice.size)A File is used for folders too. Ask is_dir which you have:
set item to mash.files.get("Finance", "Invoices")if item.is_dir printline "{{item.name}} is a folder"enditem = mash.files.get("Finance", "Invoices")if (item.is_dir) { printline("{{item.name}} is a folder")}To check first, use mash.files.exists. It answers true only when the file is there:
if mash.files.exists("Finance", "Invoices/2026/INV-2041.pdf") printline "Found it"else printline "Not there yet"endif (mash.files.exists("Finance", "Invoices/2026/INV-2041.pdf")) { printline("Found it")} else { printline("Not there yet")}Your script can only touch what the person (or automation) running it is allowed to touch. If the run isn’t allowed to read a share, the get fails like any other error. Catching an error in When things go wrong shows how to handle that.
What a file knows
Section titled “What a file knows”| Property | What it holds |
|---|---|
name | the file name, such as INV-2041.pdf |
display_name | the name without its extension |
extension | pdf, or an empty string for none |
path | the path inside the share |
size | size in bytes |
modified | when it last changed (a date) |
mimetype | the file type, such as application/pdf |
is_dir | true for a folder |
share | the share it lives on; share.name is its name |
parent | the folder it sits in |
fields | its custom fields, covered in the next chapter |
modified is a date, so you can format it. Dates in Talking to the outside world returns to dates.
Looking inside a folder
Section titled “Looking inside a folder”A folder’s contents is the list of what’s directly inside it. Loop over it as you’d loop over any array:
set folder to mash.files.get("Finance", "Invoices/2026")each folder.contents as item if item.is_dir is false and item.extension is "pdf" printline "{{item.name}} ({{item.size}} bytes)" endendfolder = mash.files.get("Finance", "Invoices/2026")each (folder.contents) as item { if (item.is_dir == false && item.extension == "pdf") { printline("{{item.name}} ({{item.size}} bytes)") }}Since contents is a plain list, wrap it in mash.collect() for sorting and totals:
set folder to mash.files.get("Finance", "Invoices/2026")set files to mash.collect(folder.contents)printline "{{files.count()}} items, {{files.sum('size')}} bytes in total"folder = mash.files.get("Finance", "Invoices/2026")files = mash.collect(folder.contents)printline("{{files.count()}} items, {{files.sum('size')}} bytes in total")Making things
Section titled “Making things”make creates a file or a folder inside a folder. Pass true as the second argument for a folder. If a folder of that name already exists, make gives you the existing one, so it’s safe to run every time:
set parent to mash.files.get("Finance", "Invoices")set folder to parent.make("2027", true)printline "Ready: {{folder.path}}"parent = mash.files.get("Finance", "Invoices")folder = parent.make("2027", true)printline("Ready: {{folder.path}}")A folder can also write text or data to a new file in it:
set folder to mash.files.get("Finance", "Notes")folder.write("hello.txt", "Hello from MaSH")folder = mash.files.get("Finance", "Notes")folder.write("hello.txt", "Hello from MaSH")Copying, moving, renaming, deleting
Section titled “Copying, moving, renaming, deleting”set file to mash.files.get("Finance", "Inbox/INV-2041.pdf")set archive to mash.files.get("Finance", "Archive/2026")
set copy to file.duplicate(archive) # a copy lands in the archivefile.rename("INV-2041-checked.pdf")file.move(archive) # the original goes there toofile = mash.files.get("Finance", "Inbox/INV-2041.pdf")archive = mash.files.get("Finance", "Archive/2026")
copy = file.duplicate(archive) # a copy lands in the archivefile.rename("INV-2041-checked.pdf")file.move(archive) # the original goes there tooWhen you copy or move, pass the destination folder object, not a path in text. Text is read as a path on the file’s own share, so a cross-share move would quietly land in the wrong place.
delete() removes a file or folder. Be careful with it. Use duplicate while you’re developing, and move to delete only when you trust the script.
Searching
Section titled “Searching”mash.files.search and mash.fields.findFiles (next chapter) find files across shares. Finding by field is usually what a workflow wants.
Try it
Section titled “Try it”Write a script that takes a folder called Inbox and prints the name of every PDF in it. Run it on a test share first.
Next, you’ll read and write the information attached to each file.