Skip to content

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.

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.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"
end

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"
end

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.

PropertyWhat it holds
namethe file name, such as INV-2041.pdf
display_namethe name without its extension
extensionpdf, or an empty string for none
paththe path inside the share
sizesize in bytes
modifiedwhen it last changed (a date)
mimetypethe file type, such as application/pdf
is_dirtrue for a folder
sharethe share it lives on; share.name is its name
parentthe folder it sits in
fieldsits 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.

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)"
end
end

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"

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}}"

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")
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 archive
file.rename("INV-2041-checked.pdf")
file.move(archive) # the original goes there too

When 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.

mash.files.search and mash.fields.findFiles (next chapter) find files across shares. Finding by field is usually what a workflow wants.

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.