cdu - Jump up to project directory

You're five levels deep in your git repo. You would like to get to the top level. 'cdu'.

An up only directory jumper for zsh and bash. Nicely complements other directory jumpers, like zoxide, autojump or fasd.

Usage example

$ pwd 
/home/tero/code/revincom/doc/design/subsystems/nav/fallbacks/sun
$ cdu
/home/tero/code/revincom
Found .git

If you have really deep repos, such as monorepos, cdu can help you even more.

Deep in a Django project, cdu jumps to manage.py level first. The next cdu will take you to repo root.

A new 'cdu', change dir up

I have used a longer bash version for years. This is a rewrite to support both zsh and bash. It's also shorter. Prettier and more features, but less tested than the old one.

Save the source code to a dir where it runs (e.g. /usr/local/bin/changedirup). Make runnable (chmod ugo+rx /usr/local/bin/changedirup). Add to your .bashrc and .zshrc: 'alias cdu="source changedirup"'. Log out and back.

And now you can jump up with 'cdu'.

Source code, GPL

#!/bin/bash
# changedirup - cd up to project top dir, 'alias cdu="source changedirup"'
# To persist it, add the alias to .zshrc or .bashrc

# Single usage also works with 'source cdu' or '. cdu'
# Can be run again to go to even higher project dir. 
# cdu works with zsh and bash. Shebang #! is just for syntax highlight.
# SPDX-License-Identifier: GPL-3.0-or-later
# SPDX-FileCopyrightText: Copyright 2020-2026 Tero Karvinen https://TeroKarvinen.com

CDU_PWD_WAS="$(pwd)"
cd ..
while true; do
	for f in .git Makefile .profile .bashrc README.md requirements.txt go.mod manage.py hosts.ini .project project.godot Dockerfile Cargo.toml index.theme config.toml default.gpr DICOMDIR ansible.cfg site.yml Vagrantfile package.json pyproject.toml zowe.yaml pom.xml build.gradle Gemfile composer.json docker-compose.yml compose.yaml .cobaltstrike.beacon_keys flake.nix  .zshrc .ssh .sliver .sliver-client .msf4 havoc_default.yaotl .projectile .svn .hg .fossil .jj .editorconfig _darcs .bzr Cargo.lock .bash_profile
	do
		if [ -e "$f" ]; then
			echo "Found $f"
			pwd
			break 2
		fi
	done

	if [ "$(pwd)" = "/" ]; then
		cd "$CDU_PWD_WAS"
		echo "No project files found above. Working directory unchanged."
		pwd
		break
	fi
	
	cd .. || break # prevent infinite loop in the rare case cd fails for permissions
done