スクリプトを実行するときにスクリプトからシェルエイリアスをエスケープするのは便利ですか?

スクリプトを実行するときにスクリプトからシェルエイリアスをエスケープするのは便利ですか?

bashソースではなく動作するシェルスクリプトでは、エスケープエイリアスは意味がありますか?


最も単純なケースを考慮すると、多くのユーザーがls機能をオーバーライドするために(inまたは)を使用します。たとえば、次のようになります。alias.bashrc.bash_aliases

alias ls='\ls --color=auto --group-directories-first'

次に、次の関数を含むシェルスクリプトを呼び出すとします。

list_sata_devices ()
{
    \ls -1 /dev/sd?
}

気づいたように強制的にオリジナル lsはい\ls、しかしこれが必要かどうか疑問に思います。


もちろんなくても書くことができますls。たとえば、次のようになります。

list_sata_devices ()
{
    printf '%s\n' /dev/sd?
}

しかし、どのような違いがあるかはまだ躊躇しています。

答え1

alias ls='\ls --color=auto --group-directories-first'

バックスラッシュは必要ありません。シェルはそのようなマイナーなループに閉じ込められません。:

代替テキストの最初の単語はエイリアスがあるかどうかをテストしますが、拡張する単語と同じエイリアスを持つ単語は再び拡張されません。


次に、次の関数を含むシェルスクリプトを呼び出すとします。

list_sata_devices ()
{
    \ls -1 /dev/sd?
}

シェルスクリプト、つまり非対話型シェルの場合、その後、エイリアスはデフォルトで無効になります。:

シェルが非対話型の場合、Shoptを使用してExpand_aliasesシェルオプションを設定しないと、エイリアスは拡張されません(Shoptの組み込みを参照)。

スクリプトはこれを明示的に有効にする必要があります(shopt -s expand_aliases) 下痢 何らかの理由でインタラクティブシェルに設定されたエイリアスを継承せず、非対話型シェルはたとえば読み取らないため、そこ.bashrcからインポートされません。非対話型シェルは次のファイルを読み込みます。$BASH_ENVそれでもそれにエイリアスを設定しない可能性があります。

したがって、ここでもバックスラッシュは必要ありません。


list_sata_devices ()
{
    printf '%s\n' /dev/sd?
}

まあ、別のコマンドです。実際には大きな効果はありませんが、ls端末に印刷すると、一部の特殊文字が異なるように処理されることがあります。

とにかくバッシュできる エクスポートと継承 機能環境によってはスクリプトがめちゃくちゃになることがありますが、一般的に誤ってそのようなことはしません。

答え2

あなたのコンテキストは、呼び出しシェルからスクリプトをインポートするのではなく、その環境でスクリプトを実行したいのと同じです。
この場合、名前が以前にエイリアスとして指定されていても、スクリプトからコマンド名をエスケープする必要はありません。

エイリアス定義を含むファイルを取得できなかった場合、エイリアスはスクリプト環境に転送されません。

スクリプトは対話型シェルではないため、スクリプトのエイリアス定義の有用性は、主に対話型コンテキストでの便宜のためであるため、疑わしいです。 (希望的に)覚えやすい略語であるcmdエイリアスは、基本的に人間と機械の間の相互作用を簡素化します(「長いコマンドをたくさん覚え、ターミナルウィンドウに入力する必要がなくなります」を参照)。

したがって、私は通常、いくつかの理由でスクリプトで事前定義されたエイリアスを使用しません。 (i) スクリプトの読みやすさ、(ii) スクリプトを定義するために外部エイリアスを使用せずに、スクリプトとその機能のすべての制御を維持します。含まれているものと含まれていないものが含まれます。あなたのスクリプト。別の場所で定義されたエイリアスに基づいてスクリプトを作成し、以前のスクリプトが実際にそれに依存していたことを覚えておらず、数ヶ月または数週間後にそのエイリアス定義を変更すると想像してください。デフォルトでは、エイリアスは子で実行されるスクリプトには転送されません。それは良いことです。シェル。

また、man bash関数内では、エイリアスは関数を読み取って使用できるようになった後にのみ拡張されます。後ろに機能が実行されます。したがって、実際にスクリプトでエイリアスを定義する場合(通常は定義しませんが、特別なユースケースがあるかもしれません)、最良の場所は別の行にあります。以上そのエイリアスを使用する関数またはcmd(ここでは、シェルでコマンドとして実行される関数を検討してください)。

最後に、スクリプトとは関係ありませんが、上部の@muruの説明は完全に有効で、Bashマニュアルにあります。エイリアス拡張に独自の名前が含まれている場合、拡張にそのエイリアス名が発生してもその名前の新しい拡張は発生しません。これにより無限再帰が発生します。したがって、以下を見ることができますが、作成する必要はありませんalias ls='\ls --color=auto --group-directories-first'。代わりに、次のように書いてくださいalias ls='ls --color=auto --group-directories-first'

ただし、古いエイリアスをエスケープすると便利ですが、次の状況では異なります。

  alias ls='ls -A --color=auto --group-directories-first'
  alias ll='\ls -l --color=auto'

ls上記の場合、エイリアスからエスケープしないと、エイリアスを定義するll最初の行で定義されたフラグとオプションが含まれますls。これは、エイリアス接続は大丈夫ですが、再帰はそうではありません。


編集する:ls -1 <foo*>との違いに関する最後の質問に答えるには、次のようにしますprintf '%s\n <foo*>

たとえば、Gnu Bash v5.1.4を実行している特定のx86_64システムでは、

 $ time for i in $(seq 10000); do \ls -1 /dev/sd* 1> /dev/null; done
 real    0m17.420s
 user    0m10.910ss
 sys     0m7.598s

 $ time for i in $(seq 10000); do printf '%s\n' /dev/sd*  1> /dev/null; done
 real    0m0.574s
 user    0m0.285s
 sys     0m0.287s

ls内蔵していても実行するのに時間がかかりますからどのように動作しますか?lstat()ファイル権限が関連付けられているときに使用されるという事実以外は、実装の詳細を理解していません。

関連情報