./ahmedhashim

One-liners: u

When you’re deep in a repo, how do you get back out again? Typing cd ../../../.. and counting the dots. I did it so many times that I made myself a function in my ~/.zshrc:

u() { cd $(printf '../%.0s' {1..${1:-1}}); }

u goes up one directory. u 3 goes up three.

Breaking it down

The argument receives a default value:

${1:-1}

This is the first argument, or 1 if there is no first argument, so a bare u goes up one.

Brace expansion handles the counting:

{1..${1:-1}}

With u 3, the range is {1..3}. That expands to three words: 1 2 3. The values don’t matter, just the count.

Which printf then turns into ../ for each word:

printf '../%.0s' 1 2 3

printf loops over that format string until there are no more arguments. %.0s consumes an argument but prints nothing from it, so each one leaves behind ../. With three arguments you get ../../../.

Wrap that in cd $(...) and you have your whole function.

Brace expansion is the zsh-only portion. Zsh does it after parameter expansion, which is why you can have a variable in a range. Bash does it backwards: the braces never expand and printf gets the single literal word {1..3}. The function still works in bash, but it never climbs past one level. Porting it would require using seq instead.

There’s one oddity: u 0 moves two directories up, because zsh expands {1..0} as a descending range to 1 0. I’ve never felt the desire to cd 0 directories up, so I never took the time to guard against it.

If I go too far, cd - puts me right back.