Move or sort a file
Moves a file into a folder, or sorts it into a subfolder named from its date, name or a counter. The folder is made when it is missing.
Move path to to
Details #
Moves the file to the folder to. With subfolder the file goes into a folder inside it, so to ~/Documents/Invoices and subfolder {added:yyyy}/{added:MM} files each invoice under its year and month. Without to, the subfolder is made next to the file (Hazel's Sort into subfolder). name gives the file a new name on the way.
When the file came from a File or folder change, path can be left out: the step acts on that file, and the run's file variable follows it, so the next step (tag it, rename it) acts on the file where it now is.
In a dry run nothing moves; the step's note says what it would do: "would move Report.pdf to ~/Archive/2026/".
Parameters #
| Parameter | Type | Required | Values | What it does |
|---|---|---|---|---|
counter | text | The name of the counter {counter} uses. | ||
createFolders | any value | Make to and the subfolder when they are missing. On by default. | ||
destination | text | |||
into | text | The variable that receives the new path. | ||
keepExtension | any value | Add the original extension to name. On by default. | ||
name | text | A new name, as a template. The extension is kept unless keepExtension is off. | ||
overwrite | text | What to do when the name is taken: rename (the default; name 2.ext), replace or skip. | ||
path | text | The file. Optional when a file trigger fired. source is another spelling. | ||
source | text | |||
subfolder | text | A folder inside to (or next to the file), as a template with the tokens below. | ||
to | text | The folder to move into. Optional when subfolder is given. destination is another spelling. |
Every step also accepts label, onFailure, timeout and dryRunSafe.
Examples #
- Sort “Report.pdf” into “~/…/Reports/{modified:yyyy}”
Gotchas #
Moving a file onto itself does nothing and says so.
A file that already exists at the destination is renamed
name 2.extunlessoverwritesaysreplaceorskip.replaceremoves the old file for good.A file trigger on the same folder does not fire again for what this run moved (the loop guard).
In a dry run it changes nothing and says what it would do.
Names and tokens #
Wherever a name or folder is a template, {{ }} works as everywhere, and these single-brace tokens are filled in by the step itself:
| Token | Gives |
|---|---|
{name} | the file name without its extension |
{ext} | the extension, without the dot |
{fullname} | the whole file name |
{parent} | the name of the folder it is in |
{added:yyyy-MM-dd} | the date the file was added to its folder (Finder's Date Added), in the format after the colon |
{created:…} {modified:…} {opened:…} | the creation, modification and last-opened dates |
{now:…} | today |
{counter:3} | a number that goes up by one each time this step runs, padded to 3 digits |
The counter is kept in shared.hazel.counter.<counter>; counter names it (the default is this macro and step), so two steps that share a counter share the numbers. It survives restarts. Write the rest of a name with {{file.name}}, {{file.ext}} and the other file fields when a file trigger fired.
See also #
Copy a file to a folder, Rename a file from a pattern, File operation