I created and added the following bash function to my bash config script a few weeks ago:
cd() {
if [ "$PS1" ]
then
if [ "$1" ]
then pushd "$1" >/dev/null && ls $LS_OPTIONS
else pushd >/dev/null && ls $LS_OPTIONS
fi
else
if [ "$1" ]
then pushd "$1" >/dev/null
else pushd >/dev/null
fi
fi
}
I haven't had problems with it until recently when it has prevented some other commands from behaving properly and I have to comment out the function. For example, when trying to clone a heroku app, I got:
environment: line 8: pushd: -P: invalid number
pushd: usage: pushd [-n] [+N | -N | dir]
environment: line 8: pushd: -P: invalid number
pushd: usage: pushd [-n] [+N | -N | dir]
environment: line 10: pushd: no other directory
And when trying to use rbenv
to install ruby, it would throw an error, something like "pwd did not return a directory", until I commented out this function.
I know just enough bash to be dangerous and I'm not sure what in the function might be causing the headaches.
Overriding cd
means that any code that expects the "regular" cd
will use your function instead. The first problem is the that your function assumes the first argument will be the directory, but your error indicates that some uses are passing different options (like -P
) as the first argument. You can fix this rather easily, simply by passing all arguments instead of just the first one. This also handles the zero argument case at the same time.
cd() {
if [ "$PS1" ]
then
pushd "$@" >/dev/null && ls $LS_OPTIONS
else
pushd "$@" >/dev/null
fi
}
However, the -P
in the error message indicates the next problem. cd
and pushd
don't take the same options, so code assuming it is calling cd
can pass options that pushd
doesn't recognize.
$ help cd | head -1
cd: cd [-L|[-P [-e]] [-@]] [dir]
$ help pushd | head -1
pushd: pushd [-n] [+N | -N | dir]
pushd
, however, can add to the directory stack without changing the directory, so you could use both commands in your function. The builtin
command lets you call the original cd
without getting stuck in infinite recursion.
cd () {
# Identify the directory argument, if any
for arg; do
case $arg in
-L | -P | -e | -@) ;;
*) dir="$arg"; break ;;
esac
done
# Process the real cd command
builtin cd "$@" &&
if [ "$dir" ]; then
# If there was a directory argument, push it on the stack
pushd -n "$dir"
fi &&
if [ "$PS1 " ]; then
# If it's an interactive shell, run ls
ls $LS_OPTIONS
fi
}
It may be simpler, though, to acknowledge that you really want to override pushd
and train yourself to use it instead of cd
.
pushd () {
builtin pushd "$@" &&
if [ "$PS1" ]; then
ls $LS_OPTIONS
fi
}