bash関数が定義されているファイルを見つける方法は?


33

__git_ps1私の場合)bash関数が定義されているファイルを見つける方法がわかりません。

私は実験しdeclaretypewhich、何も私のソースファイルを伝えていません。declareファイル名と行番号を印刷できる場所を読みましたが、どのように説明されていませんでした。のhelpページdeclareもそれを言っていません。

この情報を取得するにはどうすればよいですか?


関数のファイルへのパスが含まれていない場合$PATHは、type動作しません。findまたはを使用してみてくださいlocatelocate既存のデータベースを使用するため、はるかに高速になりますが、コマンドが最近インストールされた場合は機能しません。
user628544

回答:


37

関数を実行する準備ができている場合はset -x、実行のトレースに使用してPS4変数を設定することにより、情報を取得できます。

  1. 追加のデバッグ情報を記録--debuggerするshopt -s extdebugためにbashを使用するか、使用します。

  2. Set PS4、ソース行を表示するためにトレースするときに出力される「プロンプト」。

  3. トレースをオンにします。

  4. その後、関数を実行し、各行に対して関数のファイル名を取得できます。

  5. set +xトレースをオフにするために使用します。

この場合、次のコマンドを実行します

bash --debugger
PS4='+ ${BASH_SOURCE[0]} '
set -x ; __git_ps1 ; set +x

「-xコマンド、ケースコマンド、選択コマンド、またはコマンドの算術演算の各単純コマンドを展開した後、PS4の展開値を表示し、その後にコマンドとその展開引数または関連する単語リストを表示します。」いいね!
-l0b0

25

関数を実行する意思がない場合でも、デバッグを設定して情報を取得できます。手順は

  1. 開始bash --debuggerまたはshopt -s extdebug関数が定義される前。
  2. declare -F __git_ps1

関数が定義されている場所を報告します。

PS4で注釈付きの実行トレースを表示するのに比べて、この方法の利点は次のとおりです。

  • はるかに少ない出力
  • 質問に直接答えます

実行トレースの利点は次のとおりです。

  • 呼び出されたすべての関数を一度に表示
  • 呼び出された関数間の関係を見る
  • 再帰を参照

私は強く持つお勧めshopt -s extdebugの両方の開始時~/.bashrc~/.bash_profile異なるカバーするためにファイルを別のに使用される呼び出し例を。


1
関数が定義さshopt -s extdebugれたに呼び出さた場合にも機能します。関数がを通じて宣言されてevalいる場合、行番号がオフになる可能性があることに注意してください(現在のバグ)。
ステファンシャゼラス

私はvpncの見当違いの完了後でした。後はbash --debugger私が実際に完了したことをトリガするために持っていた定義された補完機能を取得し、それから報告取得しますdeclare -F _vpnc
ハラルド

9

@icarusの優れたソリューションは、関数が文字通りに定義されeval、別のファイルの内容の結果ではない場合に機能します(そのファイルevalはソースとして表示されます)。エイリアスのソースファイル、シェルビルトイン(たとえばecho)および実行可能ファイル(バイナリまたは非バイナリ)は出力されません。この情報は一般には利用できないと思います。一部のコマンドは、通常の実行中または信号への応答のいずれかで、ソースファイルを印刷する場合があります(また、それについて真実である場合もあります)。

__git_ps1で定義されている/usr/share/git/git-prompt.sh/usr/share/git/completion/git-prompt.sh私のシステム、アーチLinux上で、それはあなたのために同じであってもよいです。

シェルの開始時に明確にソース指定されたコマンドを探したい場合は、「呼び出し」セクションを参照しman bashてください。他のファイルをソースし、他のファイルをソースする場合があります。


起動時にソースとなるファイルのリストを取得できますbashか?
-pfnuesel

@pfnuesel-それはあなた次第です。デフォルトはin $HOME/.bashrcおよびin $HOME/.profileです。参照:linuxfromscratch.org/blfs/view/svn/postlfs/profile.htmlでは、各ファイルがいつどのように調達されるかの詳細について説明しています。
ジョー

2
@Joe gnu.org/software/bash/manual/html_node/Bash-Startup-Files.htmlは、はるかに優れたリファレンスです。/etc/profile$HOME/.bash_profile$HOME/.bash_login、との内容$ENV$BASH_ENVあなたのリストに追加する必要があります。
イカルス

@icarus-ありがとう。それはより良い説明です。
ジョー

8

で可能ではないようですbashが、zsh次のとおりです。

$ type __git_ps1
> __git_ps1 is a shell function from /usr/share/git/git-prompt.sh

質問ではbashが指定されています...
ジェフシャラー

4
@JeffSchaller:この答えを使用する明白な方法は、bashと同じファイルをソースするようにzshをセットアップし、それを使用して定義を見つけることです。この答えは、zshへの切り替えを示唆するものではなく、単にfind/ locate/ などの汎用ツールよりもシェル構文をよりよく理解できる便利なツールであることだけを示していますgrep
ピーターコーデス

@PeterCordesでは、この答えは現在、質問に答えるためにあなたが言うべきことをしていないと主張します。zshがネイティブにbashと同じファイルを読み取るかどうかはわかりません。
ジェフシャラー

@JeffSchaller:この答えは改善の必要があることに同意します。zshは、ほぼ確実に~/.whateverデフォルトでbash と同じファイルを読み取りません。また、この場合のように共有場所で定義され、再定義されていない関数に対して有用な回答を提供します~/.bashrc
ピーターコーデス

-1

同じ名前の関数を宣言し、できるだけ早く読み取り専用に設定してから、xtraceモードを有効にします。

__git_ps1(){ :;}
readonly -f __git_ps1
set -x

その後、ログインすると、ファイルのソースを含むトレース情報が表示されます。既存の読み取り専用関数を宣言しようとすると、エラーメッセージが表示されます。探している宣言を含む最後のソースファイル。

これをシステムbashプロファイルに入れる必要があるかもしれません。また、犯人を見つけた後に変更を元に戻すことを忘れないでください。


-3

これを試しましたか?

grep -rnw '/path/to/somewhere/' -e "pattern" 

またはここにある他のコマンドのいずれか:

Linuxで特定のテキストを含むすべてのファイルを見つけるにはどうすればよいですか?| スタックオーバーフロー

もっと説明をする必要があるようです。あなたの質問は「」を尋ねます。したがって、次のコマンドを実行すると、bash関数が定義されているすべてのファイルが返されます。

grep -rnw 'Path2Search' -e "#!/bin/bash"

BASHプログラミング-関数| Linuxドキュメントプロジェクト


1
リンクのみの回答は絶対に推奨されません。説明を追加してください。
heemayl
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.