Hazel can use shell scripts, or even standalone command-line programs, in either conditions or actions. In a condition, the shell script tells Hazel whether or not the file or folder being processed matches. In an action, the shell script can do pretty much anything (which may involve the file or folder being processed, but doesn’t have to). Scripts can be written in any language (including Perl or Python), as long as you tell Hazel which shell or interpreter to use.
Like AppleScript, JavaScript, and Automator, shell scripts enable Hazel to do things it’s unable to do on its own. For example, a shell script in a condition could employ the grep command to perform sophisticated pattern-matching on the file using regular expressions. A shell script in an action, likewise, can process the matched file or folder using any of innumerable command-line utilities. If you’re already comfortable writing shell scripts, using them in Hazel should be quite natural.
Unlike AppleScript and JavaScript, shell scripts in Hazel can neither accept import attributes nor export custom attributes. Shell scripts take just one argument, $1 , which is the full path of the file or folder being processed.
When working with shell scripts in Hazel, keep the following in mind:
-
The scripts execute in a different environment than in Terminal, which means that certain environment variables (such as a custom PATH and aliases) may not be set. Therefore, you should always specify the full path to any program or script, even though you might not need to do so in Terminal.
-
Along the same lines, keep in mind that $1 returns the full path, not a relative path, and that the path may contain spaces (which can cause errors in many commands if not properly accounted for). To prevent problems in the sh family of shells (zsh, tcsh, bash, etc.), enclose the path (or at least the $1 ) in quotation marks.
Embedded vs. External Shell Scripts
Hazel can run shell scripts in either of two ways:
-
Embedded: You can type (or paste) your script directly into your Hazel rule. To do this, choose “Passes shell script” as the attribute for a condition, or “Run shell script” for an action, and then click the Edit Script icon. Enter your script in the popover that appears (as illustrated below), being sure to specify the shell or interpreter in the field at the top (the default is /bin/zsh ), and click the X icon when you’re done. Embedded scripts are stored with your rules and therefore do not need to be transferred separately when copying, moving, sharing, or syncing your rules.
-
External: If your script (or other command-line program) already exists as a standalone file, you can simply point Hazel to that file. To do this, choose “Passes shell script” as the attribute for a condition, or “Run shell script” for an action, choose “Other” from the second pop-up menu, navigate to the file on disk, and click “Open.” As is the case in Terminal, the file must be executable. (That is, for user-created scripts, you should already have run chmod ugo+x script_name .) In addition, scripts must begin with a shebang ( #! ) line to indicate which interpreter to use—for example, #!/bin/bash or #!/usr/bin/perl . Because external scripts are stored separately from Hazel rules, they must also be transferred separately when copying, moving, sharing, or syncing rules to another Mac.
Shell Scripts in Rule Conditions
The goal of any script used in a rule condition (via the “Passes shell script” attribute) should be to perform a logical test that either succeeds (the condition matches) or fails (the condition does not match). Bear in mind the following:
-
Scripts used for rule conditions should return an exit status of 0 to indicate that the file or folder being processed has matched the condition. (Normally, any script or command-line program returns an exit status of 0 when it runs without errors.) Any other exit status tells Hazel that the file or folder being processed does not match the condition. This page provides various exit status examples for bash scripts; these should also work with zsh.
-
Because rule conditions tend to be evaluated many times, you should make sure the scripts runs quickly. Time-consuming scripts will greatly decrease Hazel’s performance.
-
The script must not modify any files or folders underneath the folder Hazel is monitoring, as that can result in a loop in which Hazel never stops processing the folder.
Shell Scripts in Rule Actions
When you use the “Run shell script” action, a successful match can cause any script to run—even one that has nothing to do with the file or folder you’re processing. However, most of the time you will probably want to use the shell script to perform an action on the matched file or folder, in which case your script can refer to it with the argument $1 , which represents its path.
For example, this simple script uses text-to-speech to say the entire path of whatever file or folder has matched the rule condition(s):
#!/bin/zsh
say “The file $1 matches this rule’s conditions.”
As is the case when using shell scripts in conditions, scripts used in the “Run shell script” action should return an exit status of 0 to indicate that the action was performed successfully. Any other value indicates an error, which causes Hazel to execute the rule again repeatedly until the action succeeds. (Once again, see this page for exit status examples for bash or zsh scripts.)
SEE ALSO