【发布时间】:2017-06-03 06:09:35
【问题描述】:
我正在编写一个脚本来自动创建 .gitconfig 文件。
这是我的主脚本,它调用一个函数,该函数又执行另一个文件。
dotfile.sh
COMMAND_NAME=$1
shift
ARG_NAME=$@
set +a
fail() {
echo "";
printf "\r[${RED}FAIL${RESET}] $1\n";
echo "";
exit 1;
}
set -a
sub_setup() {
info "This may overwrite existing files in your computer. Are you sure? (y/n)";
read -p "" -n 1;
echo "";
if [[ $REPLY =~ ^[Yy]$ ]]; then
for ARG in $ARG_NAME; do
local SCRIPT="~/dotfiles/setup/${ARG}.sh";
[ -f "$SCRIPT" ] && echo "Applying '$ARG'" && . "$SCRIPT" || fail "Unable to find script '$ARG'";
done;
fi;
}
case $COMMAND_NAME in
"" | "-h" | "--help")
sub_help;
;;
*)
CMD=${COMMAND_NAME/*-/}
sub_${CMD} $ARG_NAME 2> /dev/null;
if [ $? = 127 ]; then
fail "'$CMD' is not a known command or has errors.";
fi;
;;
esac;
git.sh
git_config() {
if [ ! -f "~/dotfiles/git/gitconfig_template" ]; then
fail "No gitconfig_template file found in ~/dotfiles/git/";
elif [ -f "~/dotfiles/.gitconfig" ]; then
fail ".gitconfig already exists. Delete the file and retry.";
else
echo "Setting up .gitconfig";
GIT_CREDENTIAL="cache"
[ "$(uname -s)" == "Darwin" ] && GIT_CREDENTIAL="osxkeychain";
user " - What is your GitHub author name?";
read -e GIT_AUTHORNAME;
user " - What is your GitHub author email?";
read -e GIT_AUTHOREMAIL;
user " - What is your GitHub username?";
read -e GIT_USERNAME;
if sed -e "s/AUTHORNAME/$GIT_AUTHORNAME/g" \
-e "s/AUTHOREMAIL/$GIT_AUTHOREMAIL/g" \
-e "s/USERNAME/$GIT_USERNAME/g" \
-e "s/GIT_CREDENTIAL_HELPER/$GIT_CREDENTIAL/g" \
"~/dotfiles/git/gitconfig_template" > "~/dotfiles/.gitconfig"; then
success ".gitconfig has been setup";
else
fail ".gitconfig has not been setup";
fi;
fi;
}
git_config
在控制台中
$ ./dotfile.sh --setup git
[ ?? ] This may overwrite existing files in your computer. Are you sure? (y/n)
y
Applying 'git'
Setting up .gitconfig
[ .. ] - What is your GitHub author name?
然后我看不到我在输入什么...
在dotfile.sh 的底部,我将函数调用期间发生的任何错误重定向到/dev/null。但我通常应该看到我正在输入的内容。如果我从这条线sub_${CMD} $ARG_NAME 2> /dev/null; 中删除2> /dev/null,它会起作用!!但我不明白为什么。
我需要这一行来防止我的脚本在我的命令不存在的情况下回显错误。我只想要我自己的信息。
例如
$ ./dotfile --blahblah
./dotfiles: line 153: sub_blahblah: command not found
[FAIL] 'blahblah' is not a known command or has errors
我真的不明白为什么我的子脚本中的输入被重定向到/dev/null,因为我提到只有stderr 被重定向到/dev/null。
谢谢
【问题讨论】:
-
ARG_NAME=$@错了,错了,错了。for arg in "$@"; do. -
扩展 chepner 的评论:如果您确实需要存储参数,请使用
arg_names=("$@")和for arg in "${arg_names[@]}"。此外,您确实应该有明确的 shebang 行来使脚本使用 bash 而不是通用 shell 运行(即以#!/bin/bash启动每个脚本)。 -
其实我有Shebang。我只是忘了把它贴在这里。感谢您的提示。添加这条无用的行只是不好的做法还是出于其他原因是错误的?
-
我说的是 Args,而不是 shebang。
-
@eakl 它将参数粘在一起,它们之间没有任何明确的分隔符。如果任何参数包含空格(这是完全合法的,即使在文件名中也是如此),它们将被误认为是多个文件名。此外,当您使用不带双引号的变量时,除了按空格(以及制表符和换行符)拆分外,任何包含 shell 通配符的“单词”都将扩展为匹配文件名的列表。这导致了一些非常奇怪的错误......
标签: bash stdin file-descriptor stderr io-redirection