スクリプトが複数回実行される場合、bashスクリプトを一度だけエコーするツール

スクリプトが複数回実行される場合、bashスクリプトを一度だけエコーするツール

編集:残念ながら反対票を受け取りました。これはない私のもの質問。これはLinuxが望む作業方法であり、一時的で一貫性のないインストールシナリオを使用する多くのツールがあります。私がこの質問をする理由は、一度だけ動作し、すべてが最初に完璧に動作する苦手に書かれたスクリプトを生成、採用、およびメンテナンスせずに正しいことをしたいからです。


スクリプトが特定の.bashrcファイルまたは類似のファイルに何かを反映する必要があることがよくあります。これはインストールスクリプトの文脈でも頻繁に発生するため、これらのファイルの書き込みは一度インストールスクリプトは、失敗または編集時に複数回実行される可能性があるためです。

具体的な例を挙げると、インストールするasdf、次の内容をファイルに書き込む必要があります~/.bashrc

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

インストールスクリプトでこれを使用してechoスクリプトが複数回実行されると、上記の3行が必要なだけ繰り返されます。以前にスクリプトで作成したソリューションを使用すると、次のことが発生します。

# 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

正直なところ、私は問題になるセリフを見つけて迷います。そこにいる場合は何もしないでください。そうでない場合は行を追加してください。

前任者:

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するために一緒にまとめることができます。または、3行すべてが含まれていることがわかるように、1行だけgrepで十分です。

関連情報