Skip to content

File a document into a folder named by one of its fields

What it does. A document lands in an inbox folder. Once the Customer field is filled in, the script copies the document into a folder named after the customer, and creates that folder the first time it’s needed. Running it twice for the same document does nothing the second time.

What you need.

  • The MaSH feature.
  • A share with a Customer custom field. Captur or a person fills it in.
  • Two triggers on Settings > MaSH > Events: Captur Extracted (if Captur fills the field) and Fields Changed (if a person does). Filter both to the inbox’s Path prefix, so the script doesn’t see its own filed copies. See Events.
  • Two script settings (config parameters): PARENT (the folder that holds the customer folders) and, optionally, FIELD (the field to read, default Customer).
set errorblock to "onError"
block onError
printline "Error on line {{mash.error.line}}: {{mash.error.message}}"
end
# Make a safe folder name out of a field value.
block folderNameFor raw
set name to mash.str(raw ?? "").trim().toString()
set name to mash.str(name).replaceMatches('#[\\/:*?"<>|]#', "-").toString()
return mash.str(name).trim().toString()
end
set fieldName to mash.config.get("FIELD") ?? "Customer"
set parentPath to mash.config.get("PARENT")
if not parentPath
fail "PARENT is not set on this automation."
end
set doc to mash.event.file
if not doc
return
end
if doc.is_dir
return
end
# The field is empty until Captur or a person fills it in. Wait quietly.
set folderName to folderNameFor(doc.fields[fieldName] ?? "")
if folderName is ""
return
end
set parent to mash.files.get(doc.share, parentPath)
set target to parent.make(folderName, true)
# Already filed? Then this is a repeat trigger. Stop.
if mash.files.exists(doc.share, target.path ~ "/" ~ doc.name)
return
end
set copy to doc.duplicate(target)
if not copy
fail "Could not copy {{doc.name}} into {{target.name}}"
end
printline "Filed {{doc.name}} into {{target.name}}"
  1. The error block prints the line and message of anything that goes wrong, so the run log says what happened. The Errors page explains why a run doesn’t stop by itself.
  2. folderNameFor turns a field value into a folder name. A scanned value can hold a slash or a colon, which a folder name can’t. Swapping those for - keeps the script from failing on one odd document.
  3. The guards return quietly for a run with no file, a folder, or an empty field. Both triggers fire for every document, and a run can arrive before the field is filled in. Captur Extracted or Fields Changed brings the script back when it is.
  4. parent.make(folderName, true) creates the folder, or gives you the existing one. It’s safe to run every time.
  5. The exists check is what keeps the script from looping. The copy it makes is itself a new file, and a new file can fire events again. The second time round, the copy is already there, so the script stops. Filtering the trigger to the inbox does the same job a second way.
  6. duplicate(target) takes the folder object, not a path in text. Text would be read as a path on the document’s own share.
  • Move instead of copy. Use doc.move(target). Then the inbox empties itself. The exists check is still worth keeping.
  • A second level. Add the year: target = target.make(mash.date.now().format("Y"), true). The dates section of the tutorial shows format.
  • A different share. Pass the other share to mash.files.get(otherShare, parentPath). Because duplicate takes a folder object, a copy across shares works. Check that the script’s owner can write there. See Who a script runs as.
  • Several customers’ documents in one order. The tutorial’s Putting it together gathers every document with the same order number.
  • No match, say so. Instead of returning on an empty field, print a line, so the run log shows which documents were left in the inbox.

Library pages used: Files, Fields, Core MaSH (for mash.config).