Cyber Monday Sale 40% off unlimited courses & creative assets! 40% off unlimited assets! Save Now

# Alfred Workflows for Intermediates

Welcome back! Since you are reading this, you must have enjoyed the beginner's tutorial. Great! Now, let’s dig a little deeper by making a workflow that will help manage our Downloads folder, as well as a Projects Manager.

First, create a new workflow label it Downloads Tamer. The description is set to A workflow to work with items in the Downloads folder, but you can make it whatever you want. The bundle ID is com.customct.MTDownload.

The bundle ID is very important and should be very unique to the workflow. I always use my site address and workflow name to uniquely identify the workflow.

The author can be you. The website is your website, or nothing.

## File Filters

The File Filters block is a very flexible and powerful unit. It is a great place to start working with files in a workflow. For an example, it gives an easy way to lookup files.

Select a File Filter block and complete it as shown above. Set the keyword to mtdl:today, the Placeholder Title to MT: Downloads Files, and the Placeholder Subtext to Loading Today’s Mess….

If you want to just focus on one type of file, you can drag and drop an example file to the File Types box. The intent here is to find any type of file on or around a certain day. Therefore, the File Types box is not used in this example.

Selecting Search Scope, gives us the second page of options. Using Finder, drag the Downloads directory from Finder to the Search Scope area. This tells Alfred to only search for files in these directories. Since this workflow is only interested in the Downloads folder, that will be enough.

Selecting Advanced will give us the Advanced options. Here, set the Date Range to Today so that it will only show files created today. Press Save and the first function of our workflow will be complete.

The Fields area gives a list of fields you can search for the relevant information. This can really give your search more power to find specifically what is being searched. For each field, you can set the Words flag to search inside of word bourndries. The Split flag will split each word in to separate parameters that will be individually searched.

The Accuracy flag is used to make the search not begin with a wild card if the Words flag is disabled. In other words, if the Words flag is not set, setting this flag will make the search always based on the beginning of the text and not in the middle. If the Words flag is set, this flag is meaningless.

These different flags can get confusing on how to use them. You can set up different test cases and see how each affects your results. Generally, I always keep the Words and Split flags set.

What was now created is a file browser that will only show files in the downloads directory that were added today. Now, to do something with the file selected.

From the + menu, select Open File block and attach it to the File Filter block. Now, when the mtdl:today command runs, a list of files downloaded today will appear. Selecting one will cause it to be opened in the preferred application for that file type.

Sometimes you just want to take a quick look at the file. OS X has that built in, but how to make use of it? That is where shell scripts come in handly. Add a Run Script block and connect it to the File Filter block, just like the Open File block.

Set the Language to /usr/bash. In the Script area, type qlmanage -p “{query}” >& /dev/null &. Uncheck all of the Escaping choices so your file name is not changed.

Notice the {query} macro. This macro will expand in to whatever was passed to this block from the previous block. In this case, it will be the full path to the file in the Downloads directory.

What this block will do is replace the {query} string with the full path of the file you selected, and then run the script as a bash shell script.

Tip: All scripts are executed directly without reading in your preferences files for the script type. Therefore, your “.bashrc” file will not be loaded in a bash script, nor your “.zshrc” file in a zsh script. Just the bare environment setup by the system is in place.

If the commands you use need some environment variables set, you need to either manually load the preferences file or add the environment variables to your script.

Alfred works this way to execute the scripts faster. But, it can make it hard to write scripts that work the first time!

You can connect as many blocks to a single block as you want. But, if you execute the macro now, it will open the file in its default application and in quick preview! That really is not the behaviour needed.

To fix this, double-click on the line going to the Run Script block. This will allow you to set an Action Modifier and a Modifier Subtext. Set them as you see here. What this does is allow you to switch the action of the File Filter block based on a modifier key. Now, if you just select a file, it will open in its default application. But, if you hold the Control key while selecting a file, it will preview the file instead.

The workflow should now look like this. You can see the modifier tag on the line going to the Run Script block. This way, it is easy to see how to trigger each action.

When the workflow is triggered, if you hold down the Control key, the text under the file name will be changed into Preview. It will now use the OS X preview system (Quick Look) to display the file.

The next function is to delete the file. Once again, a bash script can be used to accomplish this task. Add a Run Script block. Remember to uncheck all of the Escaping choices and set it to run a bash script.

Now for some design decisions. You could simply use the rm -f command to forcibly remove the file from the Downloads directory. But, you can never undo that decision. Therefore, it would be best to move the file to the OS X Trash folder. Since there is not a built-in command line for that, you will have to download someone else’s work and make use of it. Just remember to tell others using your workflow where to get the program. Free programs are great!

Therefore, download the trash command line program and put it in your path (/usr/local/bin would be good. The program comes with an install script as well.). Then fill in the script area with /usr/local/bin/trash “{query}”. It should look like the screenshot above.

Set that line to use the Function modifier key. Now, when you select a file with the Function key pressed, that file will be moved to the trash bin. If you want to undelete it, just open the trash folder and tell it to restore the item.

Now, add a Browse in Alfred block. This will allow us to use Alfred created actions on the files in the folder. Change the connection for the Browse in Alfred block to Shift modifier key.

Tip: You really do not need to add an Open in Finder block. That is the default action of the Command key in the Alfred Browser.

This is the Alfred Browser. Since I only have one file there right now, it is the only one shown. With that file selected, you can press the right arrow key, you will get a list of actions to take on that file.

With this list of actions, you can either scroll to see them all or start typing the name of the action to reduce the list size until you find the one you want. There are quite a few predefined file actions and many workflows add their own file actions.

Let’s suppose that the screenshot software saves images to the Downloads folder (most save to the desktop, but I do not like to clutter my desktop. Therefore, I save them to my Downloads folder.). A Send to Current Project file action would help me clean up these files in my Downloads folder.

## Project Manager Workflow

A File Action block allows for the creation of new actions to take on a file or group of files selected in the Alfred Browser. Since a Move to Current Project file action is outside the scope of a Downloads Tamer, a new workflow needs to be created for managing our project.

Create a new workflow and label it Project Manager. The description is set to A workflow to help manage your projects., but you can make it whatever you want.

The bundle ID is com.customct.MTProject. The bundle ID is very important and should be very unique to the workflow. I always use my site address in reverse lookup order (taken from DNS naming conventions) and workflow name to uniquely identify the workflow. The author can be you. The website is your website or nothing.

## File Actions

Now that we have a workflow for managing our project, we can use a File Action block to move files in to our selected project directory.

Create a File Action block with the name set to Move to Current Project. Also, check the option to accept multiple files. That way, it will be possible to select many files and have the File Action work on all of them at once. Since any type of file is allowed, you will leave the Types area blank.

In order to perform the work, you need to use a Run Script block to do the muscle job. Set the Language to /bin/bash and turn off all of the Escaping options. Set the script to:

The ~/projects/myproject should be changed to your current project’s directory. This is the hard coded approach that is not too sharable, but that will be fixed later on.

With the two blocks connected in this way, you can send any single file to our current project directory. But, the File Action block is set to allow multiple files to be sent. When multiple files are selected in Alfred Browser using Option-Shift, Alfred will send the list of files to your File Action in a tab separated list (a complete description of using the File Buffer can be found at Alfred Support .).

To fix this problem, more scripting has to be done. Change the script to the following:

Your Run Script block should now look like this:

The generate_list function is a quick way to turn the tab separated string to a list of values for the for…loop. The for…loop will assign each item in the list to the \$filen variable and perform the move. I set the project directory to a variable. The next step is to fill in the variable dynamically instead of hard coding the value.

Tip: Notice the use of double quotes around the variables in the mv statement. This insures that your path will be followed correctly even if there are spaces in the path names. This is very important to remember. Many scripts die because of this issue.

## Scripting in Alfred

In order to correct the problem of hard coding the project directory, a way to store information needs to be used. Alfred takes care of this by allowing workflows to have two data storage areas that are called data and cache.

The data storage directory is for long term storage of information. It is up to the workflow to keep the information there up to date and relavent.

The cache directory is for information that is temporary. Programs that clear out data caches on your system will automatically delete these files.

In the future, Alfred will be creating and deleting these directories automatically. But right now, it is up to the workflow to maintain them.

The data directory is located at ~/Library/Application Support/Alfred 2/Workflow Data/{BundleID}.

The cache directory is located at ~/Library/Caches/com.runningwithcrayons.Alfred–2/Workflow Data/{BundleID}.

The {BundleID} is the Bundle ID given to the workflow when you created it. Since every workflow is represented in these directories, it is very important that each workflow has a different Bundle ID.

Tip: Remember: The ~ is Unix’s way to refer to your home directory.

As you can see, these directory structures already have spaces in their names. That is why you really need to take care of them properly when you are writing scripts.

Alfred’s Run Script block allows for a varaity of programming languages to be used directly. For example, a script can be written in bash, zsh, AppleScript (also known as osascript on the command line), PHP, Python, Pearl, or Ruby. Indirectly, you can use a bash or zsh script to execute a script in some other language, like node.

The reason that Alfred only lists these languages is because they are the only languages that come on the Mac OS X platform automatically. Any other language would have be installed by the user.

Also, Alfred only calls the language from the location that it originally was installed. If you install another version of Ruby, you would have to reference it directly in a shell script instead of using the standard Ruby script descriptor in a Run Script block.

If you create a workflow that needs some other programming language installed, make sure that the user is aware of this in the description of the workflow. It is also recommended to put that information in the Readme area of the workflow.

To put this knowledge to use, you need to change the script to the following:

The section at the top is for defining our different data directory locations into constants to be used in the script. It is always good programming practices to put constant valued items into a constant for your script to use. Therefore, if it needs to be changed latter, it will be a very simple thing to do.

Next, the function getBundleId uses a program in OS X to read the plist for the workflow, info.plist, and retrieve that id. The plist is located in the workflows directory. When you look at a Run Script block, you will notice at the bottom right of the script window is a button labeled Open workflow folder. That will open the folder for your workflow in Finder.

If your program makes use of graphics or other scripts that never are changed, this is a great area to store them. When you share a workflow, this entire directory is zipped up in to the workflow file.

The getDataDir function simply uses the constants defined and the Bundle ID to create the location of the data directory. The cache directory is not used in this example.

The if block is used to create our data directory and the data file used for the project directory storage if they do not already exist. All of the scripts you write that make use of these directories needs to have this type of coding to work properly. Do not rely on an initialization keyword as the user might not use it first!

The next change is how the projDir variable is defined. Simply cat the contents of the projectDir.txt file in to the variable. Therefore, that file should have a single line that contains the directory for our project.

After getting the projectDir variable set, the validity of the data needs to be checked. If the user has not set a project directory yet, then the variable should be blank. Therefore, the script will test for a blank variable. If it is blank, send a warning message and exit.

Tip: Always make sure your data is correct. This keeps many errors out of your workflows and helps others feel like you really delivered a good product. If you forget this, you can be sure that it will come back to pester you to death!

At the very end, the script tells the user that the file(s) were moved. I always like to give feedback to the user. It helps the user to feel like something is getting done. Therefore, the messages need to be displayed in a Post Notification block. Add one to the end of the workflow. Your workflow should look like the above picture.

If the projectDir.txt file was just created by the script, then it will not contain any information. Therefore, a way to set this file needs to be made! The easiest way is to use a File Filter block set to directories like in the first tutorial. Add a File Filter block and fill it in as seen.

Now, add a Run Script block with the following script:

Notice, this time the {query} macro is used twice. You can use it as many times as you like in the scripts.

The directory passed from the File Filter block will always be a valid directory. Therefore, it does not need to be tested. Just echo it into the file in our data directory and it is safe.

When you connect the Run Script block to the Post Notification block, it should look like the above picture. Now the project directory can be set and changed with ease.

## Conclusion

Now you have two new workflows to help you in your daily routines: one to go through your Downloads folder and one to manage your projects. Try to expand them with more useful features. For example, create a File Filter and Open File action to edit your project files, or copy the file deletion code from the Downloads Tamer workflow to delete files from your project. You never learn until you try things on your own!

The advanced tutorial will expand these two workflows with even more complex scripting and make use of other libraries to make working with Alfred workflows easier. Have fun scripting!

Update: A new workflow sharing site is now available: Packal that promises to have a workflow to work with this site as well.