bash 脚本不能很好地与其他命令行实用程序一起使用
bash script not playing nicely with other command line utilities
几周前我创建了以下 bash 函数并将其添加到我的 bash 配置脚本中:
cd() {
if [ "$PS1" ]
then
if [ "" ]
then pushd "" >/dev/null && ls $LS_OPTIONS
else pushd >/dev/null && ls $LS_OPTIONS
fi
else
if [ "" ]
then pushd "" >/dev/null
else pushd >/dev/null
fi
fi
}
直到最近我才遇到问题,当时它阻止了一些其他命令的正常运行,我不得不注释掉该功能。例如,在尝试克隆 heroku 应用程序时,我得到:
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
并且当尝试使用 rbenv
安装 ruby 时,它会抛出一个错误,类似于 "pwd did not return a directory",直到我注释掉这个函数。
我只知道 bash 是危险的,我不确定函数中的什么可能导致头痛。
覆盖 cd
意味着任何需要 "regular" cd
的代码都将使用您的函数。第一个问题是您的函数假定第一个参数是目录,但您的错误表明某些用途正在传递不同的选项(如 -P
)作为第一个参数。您可以很容易地解决这个问题,只需传递 all 个参数,而不仅仅是第一个参数。这也同时处理零参数情况。
cd() {
if [ "$PS1" ]
then
pushd "$@" >/dev/null && ls $LS_OPTIONS
else
pushd "$@" >/dev/null
fi
}
但是,错误信息中的-P
表示下一个问题。 cd
和 pushd
不采用相同的选项,因此假设调用 cd
的代码可以传递 pushd
无法识别的选项。
$ help cd | head -1
cd: cd [-L|[-P [-e]] [-@]] [dir]
$ help pushd | head -1
pushd: pushd [-n] [+N | -N | dir]
但是,pushd
可以添加到目录堆栈 而无需 更改目录,因此您可以在函数中使用这两个命令。 builtin
命令可让您调用原始 cd
而不会陷入无限递归。
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
}
不过,承认您确实想要覆盖 pushd
并训练自己使用它而不是 cd
可能更简单。
pushd () {
builtin pushd "$@" &&
if [ "$PS1" ]; then
ls $LS_OPTIONS
fi
}
几周前我创建了以下 bash 函数并将其添加到我的 bash 配置脚本中:
cd() {
if [ "$PS1" ]
then
if [ "" ]
then pushd "" >/dev/null && ls $LS_OPTIONS
else pushd >/dev/null && ls $LS_OPTIONS
fi
else
if [ "" ]
then pushd "" >/dev/null
else pushd >/dev/null
fi
fi
}
直到最近我才遇到问题,当时它阻止了一些其他命令的正常运行,我不得不注释掉该功能。例如,在尝试克隆 heroku 应用程序时,我得到:
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
并且当尝试使用 rbenv
安装 ruby 时,它会抛出一个错误,类似于 "pwd did not return a directory",直到我注释掉这个函数。
我只知道 bash 是危险的,我不确定函数中的什么可能导致头痛。
覆盖 cd
意味着任何需要 "regular" cd
的代码都将使用您的函数。第一个问题是您的函数假定第一个参数是目录,但您的错误表明某些用途正在传递不同的选项(如 -P
)作为第一个参数。您可以很容易地解决这个问题,只需传递 all 个参数,而不仅仅是第一个参数。这也同时处理零参数情况。
cd() {
if [ "$PS1" ]
then
pushd "$@" >/dev/null && ls $LS_OPTIONS
else
pushd "$@" >/dev/null
fi
}
但是,错误信息中的-P
表示下一个问题。 cd
和 pushd
不采用相同的选项,因此假设调用 cd
的代码可以传递 pushd
无法识别的选项。
$ help cd | head -1
cd: cd [-L|[-P [-e]] [-@]] [dir]
$ help pushd | head -1
pushd: pushd [-n] [+N | -N | dir]
但是,pushd
可以添加到目录堆栈 而无需 更改目录,因此您可以在函数中使用这两个命令。 builtin
命令可让您调用原始 cd
而不会陷入无限递归。
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
}
不过,承认您确实想要覆盖 pushd
并训练自己使用它而不是 cd
可能更简单。
pushd () {
builtin pushd "$@" &&
if [ "$PS1" ]; then
ls $LS_OPTIONS
fi
}