実行中のスクリプトを含むディレクトリへのパスを確実に識別します。

実行中のスクリプトを含むディレクトリへのパスを確実に識別します。

SOには、この問題を解決する多くの答えがあります。

少し残ったエマルジョンUnixとLinuxで源泉スクリプト。

ただし、その一部はBashにのみ適用されます(Bashに依存しています$BASH_SOURCE)。それらの一部ディレクトリ名に改行文字が含まれている場合は機能しませんが、一部はシンボリックリンクが含まれていると正しく機能しません。

何ですか信頼できるすべてのデフォルトシェルで実行/呼び出しスクリプトを含むディレクトリへのパスを取得するには?各シェルタイプを確認するソリューションがあれば良いでしょう。

ベストアンサー1

私はこれを初めて試してみます。他の人も改善されることを願っています。

スクリプトを実行する前に、シェルはファイルのファイル記述子を開きます。通常、fd 255に割り当てられます。とにかくオープンがあれば見つけることができますfdlsofだから私たちはlsof -p $$最高のファイル記述子のファイル名を使用して取得します。lsofすべてのUNIXバージョンに適用されるわけではありません。 BSD Wikiには同等のものがあることがわかりますfstat。 Darwin(Mac OS)にあるようです。 `-Fで

スクリプト例:

#!/bin/sh

this_script_path=`lsof -p $$  | awk '/\/'${0##*/}'$/' | cut -c 55-`

明らかに、クリッピングはlsofの特定の形式に大きく依存します。バージョン 2 では、この問題を軽減できます。注:私のバージョンでは、lsof印刷できない文字を変換してパス名のタブ文字も\t

バージョン2。醜いPerlコードについて事前に申し訳ありません。今回は-Fオプションを使って出力を制御します。私たちは-F fn次のような結果を得るでしょう:

p3834
fcwd
n/home/joe/test
frtd
n/
ftxt
n/bin/bash
fmem
n/lib64/ld-2.12.so
fmem
n/lib64/libdl-2.12.so
fmem
n/lib64/libc-2.12.so
fmem
n/lib64/libtinfo.so.5.7
fmem
n/usr/lib/locale/locale-archive
fmem
n/usr/lib64/gconv/gconv-modules.cache
f0
n/dev/pts/1
f1
n/dev/pts/1
f2
n/dev/pts/1
f255
n/home/joe/test/t.sh

私たちは、最高のファイル記述子(255と信じられないと仮定します)がスクリプト名になるように、この混乱した部分を変換する必要があります。 (これもdash当てはまるようです。)

this_script_path=`lsof -p $$ -F fn | 
  perl -lane '
        $fd=$1,next if /^f(\d+)/; 
        $p{$fd}=$1 if $fd and /^n(.*)/;
        $fd="";
  }END { 
        @x=sort {$a<=>$b} keys %p;
        print $p{$x[-1]}; 
  }{'`

Perlスクリプトは見苦しいことに同意します。これは一行で、明確にするために分類しました。行が始まると、ファイル記述子の番号がキャプチャされます。f有効なファイル記述子と有効なファイル名がある場合は、ファイル名をハッシュとしてキャプチャします。これらの条件のいずれも満たしていない場合は、キャンセルしてください$fd。すべての行が処理されたら、ハッシュ(ファイル記述子)のキーを数字でソートし、結果を配列に保存し、配列の最後の要素(最も大きい値)でインデックス付けされたxファイル名hashの内容を出力します。px

唯一の質問は、lsofがすべてのシステムにインストールされているかどうか、およびこの出力形式がどれほど安定しているかです。

おすすめ記事