Bash 脚本:如果该行尚不存在,则仅将行回显到 ~/.bash_profile 一次

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4479579/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-17 23:07:30  来源:igfitidea点击:

Bash script: only echo line to ~/.bash_profile once if the line doesn't yet exist

bashshellscriptingsedgrep

提问by ma11hew28

I wrote a bash git-install script. Toward the end, I do:

我写了一个bash git-install 脚本。最后,我这样做:

echo "Edit ~/.bash_profile to load ~/.git-completioin.bash on Terminal launch"
echo "source ~/.git-completion.bash" >> ~/.bash_profile

The problem is, if you run the script more than once, you end up appending this line multiple times to ~/.bash_profile. How do I use bash scripting with grepor sed(or another option you may recommend) to only add the line if it doesn't yet exist in the file. Also, I want to add the line to ~/.profileif that file exists and ~/.bash_profiledoesn't exist, otherwise just add it to ~/.bash_profile.

问题是,如果您多次运行该脚本,最终会将此行多次附加到 ~/.bash_profile。我如何使用 bash 脚本grepsed(或您可能推荐的其他选项)仅添加文件中尚不存在的行。另外,~/.profile如果该文件存在和~/.bash_profile不存在,我想添加该行,否则只需将其添加到~/.bash_profile.

回答by camh

Something like this should do it:

像这样的事情应该这样做:

LINE_TO_ADD=". ~/.git-completion.bash"

check_if_line_exists()
{
    # grep wont care if one or both files dont exist.
    grep -qsFx "$LINE_TO_ADD" ~/.profile ~/.bash_profile
}

add_line_to_profile()
{
    profile=~/.profile
    [ -w "$profile" ] || profile=~/.bash_profile
    printf "%s\n" "$LINE_TO_ADD" >> "$profile"
}

check_if_line_exists || add_line_to_profile

A couple of notes:

一些注意事项:

  • I've used the .command instead of sourceas sourceis a bashism, but .profilemay be used by non-bash shells. The command source ...is an error in .profile
  • I've used printfinstead of echobecause it's more portable and wont screw up backslash-escaped characters as bash's echowould.
  • Try to be a little more robust to non-obvious failures. In this case make sure .profile exists and is writablebefore trying to write to it.
  • I use grep -Fxto search for the string. -Fmeans fixed strings, so no special characters in the search string needs to be escaped, and -xmeans match the whole line only. The -qsis common grep syntax for just checking the existence of a string and not to show it.
  • This is proof of concept. I didn't actually run this. My bad, but it's Sunday morning and I want to go out and play.
  • 我使用了.命令而不是sourceas sourceis a bashism,但.profile可能会被非 bash shell 使用。该命令source ...是一个错误.profile
  • 我使用了printf而不是echo因为它更便携并且不会像 bash 那样搞砸反斜杠转义的字符echo
  • 尝试对不明显的故障更加稳健。在这种情况下在尝试写入之前确保 .profile 存在且可写。
  • grep -Fx用来搜索字符串。-F表示固定字符串,所以搜索字符串中没有特殊字符需要转义,-x表示只匹配整行。该-qs是只检查一个字符串的存在,而不是显示它的grep常见的语法。
  • 这是概念证明。我实际上没有运行这个。我的不好,但现在是星期天早上,我想出去玩。

回答by Wayne E. Seguin

if [[ ! -s "$HOME/.bash_profile" && -s "$HOME/.profile" ]] ; then
  profile_file="$HOME/.profile"
else
  profile_file="$HOME/.bash_profile"
fi

if ! grep -q 'git-completion.bash' "${profile_file}" ; then
  echo "Editing ${profile_file} to load ~/.git-completioin.bash on Terminal launch"
  echo "source \"$HOME/.git-completion.bash\"" >> "${profile_file}"
fi

回答by thkala

How about:

怎么样:

grep -q '^source ~/\.git-completion\.bash$' ~/.bash_profile || echo "source ~/.git-completion.bash" >> ~/.bash_profile

or in a more explicit (and readable) form:

或更明确(和可读)的形式:

if ! grep -q '^source ~/\.git-completion\.bash$' ~/.bash_profile; then
    echo "Updating" ~/.bash_profile

    echo "source ~/.git-completion.bash" >> ~/.bash_profile
fi

EDIT:

编辑:

You should probably add an additional newline before your one-liner, just in case ~/.bash_profiledoes not end in one:

您可能应该在单行之前添加一个额外的换行符,以防万一~/.bash_profile不以一个结尾:

if ! grep -q '^source ~/\.git-completion\.bash$' ~/.bash_profile; then
    echo "Updating" ~/.bash_profile

    echo >> ~/.bash_profile   
    echo "source ~/.git-completion.bash" >> ~/.bash_profile
fi

EDIT 2:

编辑2:

This is a bit easier to modify and slightly more portable:

这更容易修改并且更便携:

LINE='source ~/.git-completion.bash'

if ! grep -Fx "$LINE" ~/.bash_profile >/dev/null 2>/dev/null; then
    echo "Updating" ~/.bash_profile

    echo >> ~/.bash_profile   
    echo "$LINE" >> ~/.bash_profile
fi

The -Fand -xoptions are specified by POSIX and were suggested in several other answers and comments.

-F-x选项由POSIX规定,并提出其他几个答案和评论。

回答by Laurence Gonsalves

# Decide which profile to add to
PROFILE=~/.bash_profile
if ! [ -e "$PROFILE" ] && [ -e ~/.profile ]; then
    PROFILE=~/.profile
fi

# Add to profile if it doesn't appear to be there already. Err on the side of
# not adding it, in case user has made edits to their profile.
if ! grep -s 'git-completion\.bash' "$PROFILE"; then
    echo "Editing $PROFILE to load ~/.git-completion.bash on Terminal launch"
    echo "source ~/.git-completion.bash" >> "$PROFILE"
fi