Mac migration 02 – list files and folders (and their sizes)

This is the second installment of my Mac migration series.In this series I am writing about the scripts and code I am developing with the ultimate goal of fully automating the process of taking an existing production Mac workstation and moving it to a new hardware model while providing a seamless upgrade experience to the end user.  See my first article here: Mac migration 01 – list all mapped printers on the system. The scripts in this article will loop through every non-system folder/file on the Mac, record it’s size, and write a log file with the name, size (in human readable terms), and total approximate size of the data transfer that will take place.  As with the last article about listing printers, I’ve written code in both Applescript and bash. Both play nicely with JAMF, the Mac management tool of choice at my company, and are fairly easy to read and write.

Essentially both scripts access only the “Work” partition on the Mac, but the bash script was written in a modular fashion as a set of independent functions, and references only ‘/Volumes/$WorkPartition,’ so in theory you could assign any valid partition name to WorkPartition before calling this function. It should work “right out of the box.” Mac building procedures at my company result in the /Users folder being redirected to a separate partition (via sym link) that contains no system files or applications, only user data. And since standard users do not have permissions to write to the boot partition, we will never miss any user data by ignoring the boot partition. This makes reimaging a system on the fly super easy (and fast since there is no need to backup user data), especially when combined with the bless command. I write about the method I use here: netboot across subnets, or how to use the bless command.

Both scripts call secondary functions to calculate the size of each file/folder found and convert it to human readable terms (GB, MB, KB) before writing it to a log. IMO, bash is variable scoping challenged, so I tend to make all of my variables global and give them unique names, unless they are one-use throw aways like i or x in a for loop. I also make sure to explicitly reset their values when needed, etc. Also, since bash does not allow you to pass variables as arguments to a function (not really, anyway), you must make sure to declare the value of each variable a function will reference before you call that function. Otherwise it may operate on an incorrect value in the case of a globally scoped variable, or no variable at all (since a function only knows about it’s own local and globally-scoped variables, and not about a different function’s variables) in the case of a locally scoped variable. I’ve found it easier to globally declare any variable whose value must pass between functions.

Finally, both scripts record the total approximate size of user data to transfer found on the “Work” partition. I use these recorded sizes to approximate how long certain computers will take to migrate based on how much data they have vs average transfer speed of a FW800 cable and TDM. Unfortunately we do not have any Thunderbolt enabled Macs that will need to be migrated for quite some time – my company has a 4-year refresh cycle, so I am currently battling for disk quotas set at 100 GB max for the user-writable space, 60 GB for the boot partition, and to use the rest as a hidden rescue partition.


Since the code snippet is actually fairly long, I’ve linked to a pre-compiled .scpt file here:


The bash script is also fairly long, so I’ve linked to it here: Make sure to make it executable before trying to run it.

About this entry