Date: Mon, 9 Feb 2026 12:04:29 -0500
From: Greg Wooledge <[email protected]>
Message-ID: <[email protected]>
| You could implement this yourself with a function.
Yes, that is absolutely the right way.
| I would suggest not overriding the "cd" name
That depends how it is implemented, make it an option to cd
(and implement that in a function, which uses the command to
do the work) and it would be ok.
so cd -u3
or something would work just fine, you could also make cd -3
(and similar) work, as options, rather than args, if you're
willing to limit the parameter to a single digit (no cd -11).
| up() {
| local i
| for ((i=0; i < $1; i++)); do cd .. || return 1; done
| }
But that's absolutely the wrong way to do it (and not just because
it is using a bashism that isn't needed for this).
The issue is that if, somewhere between the first and last "cd .."
one of them fails, that function will correctly report something
like
cd .. permission denied
but then the current directory is who knows where. How many cd ..'s
worked before the one that failed.
The correct approach for this is something more like
up() {
local i=0
local p=.
test "$#" -gt 0 || set -- 1
while [ "$i" -lt "$1" ]
do
p=${p}/..
done
cd "$p"
}
(don't need the || return for this, the status of the "cd" will be
the return value of the function).
No bashisms (beyond "local" - but all shells have that these days,
the only reason it is not in POSIX is that the underlying variable model
that it implements isn't agreed, and that makes differences in obscure
aspects of the command - but nothing which matters for this simple usage).
And it either works as requested, or it doesn't, in which case $PWD is
unaltered, you remain in the directory where you started.
kre
ps: it is still possible to write all that on one line, if that is what
really floats you boat.