Fast, fuzzy directory navigation for Tag Filer

This script provides an easy way to jump around the filesystem if (and only if) you’re using my Tag Filer system. In that system, you tag main “context” folders with “=Tagname,” and target subfolders (project folders) with “@projecttag.” The Tag Filing system allows me to tag individual files and folders with a “#Tagname” (target context) and “:project:chain” tags to have Hazel automatically move them to their destination and maintain both a shallow folder system and a tag-based search system. Get more info here.

If you have such a setup, you can source the function below in your profile and have a cdt command available. Then, typing cdt work projectx will jump to the folder tagged “@projectx” inside of the context folder tagged “=Work.” The command requires a context as the first argument, and any subsequent tags are project folders, but it’s forgiving about capitalization and partial tags.

In fact, it’s even fuzzy, so you could type cdt wrk projx. You can also reach subfolders in sequence, which is handy because after the project folder I often have subfolders (e.g. asset folders) with the same name as other projects’ folders. In this scenario, cdt wrk projx img will jump me to ~/Dropbox/Work/project-x/images/ instantly.

cdt.bashraw
# In my tag-filing system where top-level "context" folders are tagged with
# "=Context" tags and subfolders are tagged with "@project" tags, this function
# lets me quickly cd to any tagged folder in my filing system. The first
# argument is a context folder, the rest are a chain of subfolders. The
# subfolders don't need to be contiguous, and the matching is fuzzy.
cdt() {
	local fuzzy
	local root
	local sub
	local list

	if [[ $# == 0 || $1 =~ ^\-?\-h(elp)?$ ]]; then
		cat <<-EOS
			$FUNCNAME changes directory based on tagged folders
			usage: $FUNCNAME context [subfolder, [subfolder...]]
		EOS
		return
	fi

	fuzzy=`echo ${1##[#=]} | sed 's/\([[:alpha:]]\)/\1*/g'`
	root=`mdfind "kMDItemUserTags = '=*$fuzzy'c && kMDItemContentType = 'public.folder'"|head -n 1`

	if [[ $2 ]]; then
		shift
		while [[ $1 ]]; do
			fuzzy=`echo $1 | tr -d "@: " | sed 's/\([[:alpha:]]\)/\1*/g'`
			sub=`mdfind -onlyin "$root" "kMDItemUserTags = '@$fuzzy'c && kMDItemContentType = 'public.folder'"|head -n 1`
			list=`ls -1F | grep -i "${fuzzy//\*/.*}.*\/$" | head -n 1`
			if [[ -n $sub ]]; then
				root=$sub
			elif [[ -d $root/$list ]]; then
				root=$list
			fi
			shift
		done
	fi

	builtin cd "$root"
}
Brett Terpstra

Brett is a writer and developer living in Minnesota, USA. You can follow him as ttscoff on Twitter, GitHub, and Mastodon. Keep up with this blog by subscribing in your favorite news reader.

This content is supported by readers like you.