如果脚本运行多次,则仅回显 bash 脚本一次的工具

如果脚本运行多次,则仅回显 bash 脚本一次的工具

编辑:不幸的是,反对票。这不是我的问题。这就是 Linux 希望完成任务的方式,以及无数具有临时和不一致安装场景的工具。我问这个问题是因为我想做正确的事情,而不必创建、采用和维护写得不好的脚本,这些脚本只有运行一次才能正常工作,并且在第一次运行时一切都完美运行。


经常会出现脚本需要将某些内容回显到某个.bashrc或类似文件的情况。由于这也经常出现在安装脚本的上下文中,因此这样的文件写入应该只发生一次因为安装脚本可能会在发生故障或编辑时多次运行。

作为一个具体的例子,当安装asdf,需要将以下内容写入文件~/.bashrc

# asdf
. "$HOME/.asdf/asdf.sh"
. "$HOME/.asdf/completions/asdf.bash"

如果echo只是在安装脚本中使用,并且该脚本运行多次,那么您将得到上述三行重复的次数。这就是当您使用我之前在脚本中编写的解决方案时会发生的情况:

# Install asdf
sudo apt-get install curl git -y
git clone https://github.com/asdf-vm/asdf.git ~/.asdf --branch v0.13.1
echo $'\n# asdf' >> ~/.bashrc
echo '. $HOME/.asdf/asdf.sh' >> ~/.bashrc
echo '. $HOME/.asdf/completions/asdf.bash' >> ~/.bashrc
source ~/.bashrc

现在,我可以使用适当的脚本语言(例如 PowerShell 或可脚本编程语言)来处理此问题,但如何在纯脚本中最好地处理此问题bash?有工具可以帮助解决这个问题吗?我假设有一些神奇的实用程序可以串在一起,这些都是可以接受的答案,但是该工具越专注于这个问题就越好。

我可能希望有一个解决方案某物喜欢:

# <asdf-begin>
. "$HOME/.asdf/asdf.sh"
. "$HOME/.asdf/completions/asdf.bash"
# <asdf-end>

如果脚本中在各部分之间执行实际操作的部分会加分改变,然后重新运行脚本将在开始行和结束行之间更新,而不是编写一个全新的块。

答案1

在我向您展示如何解决您原来的问题之前,首先让我向您展示正确的方法:

如果您具有 root 权限,则只需将文件安装到用于此目的的目录中即可。这将为所有用户安装 asdf。

cp ~/.asdf/completions/asdf.bash /usr/share/bash-completion/completions/asdf
cp ~/.asdf/asdf.sh /etc/profile.d/asdf.sh

如果您没有 root 权限,请~/.local/share/bash-completion/completions/按照以下步骤安装完成脚本用户定义的 bash_completion.d 脚本的标准位置?(这需要bash-completion安装)。我不知道标准用户等效的,/etc/profile.d/但你可以轻松地制作你自己的:/etc/profile应该包含这些行:

# Load profiles from /etc/profile.d
if test -d /etc/profile.d/; then
    for profile in /etc/profile.d/*.sh; do
        test -r "$profile" && . "$profile"
    done
    unset profile
fi

让我们从中汲取灵感,并将以下几行放入~/.profile

if test -d ~/profile.d/; then
    for profile in ~/profile.d/*.sh; do
        test -r "$profile" && . "$profile"
    done
    unset profile
fi

然后你就可以简单地做cp ~/.asdf/asdf.sh ~/profile.d/asdf.sh。即使已经安装了 asdf,这也将起作用。

顺便说一句,我建议使用 Linux 发行版的包管理器,而不是手动安装软件。写包并不难。看谴责对于现有的包和这里一个 Arch Linux 的例子。

解决你原来的问题

if grep -wq 'asdf.sh' ~/.bashrc; then
    : # asdf already installed, do nothing
else
    echo '. $HOME/.asdf/asdf.sh' >> ~/.bashrc
fi

<asdf-begin>为了获得奖励积分,您可以使用 GNU sed 首先删除和之间的行<asdf-end>,然后写入更新的块:

sed -i '/<asdf-begin>/,/<asdf-end>/d' ~/.bashrc
cat <<'EOF' >>~/.bashrc
# <asdf-begin>
. "$HOME/.asdf/asdf.sh"
# <asdf-end>
EOF

答案2

老实说,我只会 grep 查找有问题的行。如果它们在那里,则不要执行任何操作,如果没有,请添加这些行。

前任:

line1=$(grep "asdf.bash" ~/.bashrc)
if [ ! -z "$line1" ];
then
  echo "Lines are present, continue"
else
  echo '. $HOME/.asdf/asdf.sh' >> ~/.bashrc
  echo '. $HOME/.asdf/completions/asdf.bash' >> ~/.bashrc
fi

当然,可以将其串在一起以 grep 查找多行,或者如果您只需要 grep 查找一行即可知道所有 3 行都在其中,那么也足够了。

相关内容