sourceコマンドを使用して外部スクリプトを起動する

sourceコマンドを使用して外部スクリプトを起動する

私は素晴らしいチュートリアルとスクリプトを読んでシェルスクリプトを学びました。

私はこれを読んでいますMinecraft初期化スクリプト、最初の行は私に深い印象を残しました。

if [ -L $0 ]
then
    source `readlink -e $0 | sed "s:[^/]*$:config:"`
else
    source `echo $0 | sed "s:[^/]*$:config:"`
fi

したがって、この行は同じシェル(すべての設定値が保存される場所)で "config"というスクリプトを起動します。しかし、なぜファイルを直接実行するのではなく(「ソース設定」などを使用して)、スクリプトの作成者は元のスクリプトの名前(リンクであるかどうかにかかわらず)を読み取り、結果を送信してsedその名前を置き換えます。 「構成」で?

答え1

ソースコードの使用

このコマンドはsource他のスクリプトを実行しません。他のスクリプトの内容をこのスクリプトにインポートし、その内容が元の呼び出しスクリプトの一部であるかのように実行します。

これは基本的に、他のスクリプトの内容を自分と同じ範囲に含めるメカニズムです。

読み取りリンクの使用

このコマンドは、ソーススクリプトがリンクを介して呼び出される場合に存在します。

sedを使う

このスクリプトはsedを使用して呼び出しスクリプトの名前をnameに変換しますconfig

はい

次のスクリプトがあるとしますorig.bash

#!/bin/bash

printf "exectued as:  %s\n" $0
cmd=$(readlink -e $0 | sed "s:[^/]*$:config:")
printf "sourcing as:  %s\n" "$cmd"

このプログラムは2つのことを行います。

  1. 印刷された値$0

    printf "exectued as:  %s\n" $0
    
  2. readlink ...印刷コマンド値

    cmd=$(readlink -e $0 | sed "s:[^/]*$:config:")
    printf "sourcing as:  %s\n" "$cmd"
    

それでは、このスクリプトへのリンクを作成しましょうlink2orig.bash。ディレクトリに次のファイルがあります。

# creates link
$ ln -s orig.bash link2orig.bash

# results after
$ ls -l
total 4
lrwxrwxrwx 1 saml saml   9 Sep  5 06:23 link2orig.bash -> orig.bash
-rwxrwxr-x 1 saml saml 126 Sep  5 06:31 orig.bash

今何が起こるのか見てみましょう

実際の名前またはリンクを使用してサンプルスクリプトを実行すると、文字列を呼び出し元の引数に置き換えることができますconfig。これは、私たちが調達しているスクリプトの構成情報を含む別のファイルです。

$ ./orig.bash 
executed as:  ./orig.bash
sourcing as:  /home/saml/tst/89518/config

$ ./link2orig.bash 
executed as:  ./link2orig.bash
sourcing as:  /home/saml/tst/89518/config

ご存知のように、このアプローチの利点の1つは、システムのさまざまな場所でさまざまな方法で呼び出されることに非常に寛大です。

$ ../89518/orig.bash 
executed as:  ../89518/orig.bash
sourcing as:  /home/saml/tst/89518/config

$ ../89518/link2orig.bash 
executed as:  ../89518/link2orig.bash
sourcing as:  /home/saml/tst/89518/config

答え2

$0スクリプトへのパスです。通常、スクリプトのフルパスです(つまり、で始まる絶対パス/)。スクリプトが実行可能でshebang行で始まる一般的な場合、パスはフルパスになります。ただし、シェルが明示的に呼び出される場合、$0これはユーザーがコマンドラインに入力するすべてのエントリであり、パスを含めない可能性があります(cd somedir; bash minecraft$0isを使用minecraft)。標準入力でスクリプトを使用してシェルを呼び出す場合、$0シェルの名前またはパス(bash <minecraft、、$0is bash)。

シンボリックリンクを介してスクリプトにアクセスすると、スクリプトはリンクのフルパスとreadlinkLinux関連ユーティリティを介して拡張シンボリックリンクを検索します。

名前変換はスクリプトのデフォルト名をconfig。つまり、yesの場合$0(またはreadlink $0場合によっては)/path/to/minecraftsedコマンドはを出力します/path/to/config。パスに以下が含まれていない場合でも機能します/minecraftconfig

スクリプトの要点は、configスクリプトと同じディレクトリで呼び出されたファイルを見つけてそのファイルを取得することです(つまり、呼び出しスクリプトと同じコンテキストでスクリプトを読み込んで実行すること)。後でスクリプトで使用される変数をconfig定義する設定ファイルです。minecraft

スクリプトがありません変数とコマンドの置換は二重引用符で囲まれています。。次のように書く必要があります。

if [ -L "$0" ]
then
    source "$(readlink -e "$0" | sed 's:[^/]*$:config:')"
else
    source "$(echo "$0" | sed 's:[^/]*$:config:')"
fi

スクリプトパスに-改行文字が含まれているか含まれている場合はまだ失敗しますが、この場合はまれです。

シェル文字列操作構成を使用して、同じアイデア(への外部呼び出しを除くreadlink)を作成できます。

case $0 in */*) config=$0;; *) config=./$0;; esac  # make sure there is a / in $config
if [ -L "$config" ]; then config=$(readlink -e -- "$config"); fi
config=${config%/*}/config

関連情報