web-dev-qa-db-ja.com

シンボリックリンクを見つけるために「realpath」を取得するにはどうすればよいですか?

私はMacOSXでシェルとしてbashを使用しています。次のように作成されたシンボリックリンクがあります。

ln -s /usr/bin/python python2 

私はpython2を使用するパッケージを持っています。現在の作業ディレクトリに/usr/bin/pythonへのシンボルリンクを作成します。これは実際にはpython2です。コマンドラインからpython2を実行すると、次のエラーが発生します。

python2: realpath couldn't resolve "/usr/bin/python2"

ただし、このように呼び出すと、./python2によってパスが正しく解決されます。私のPATHには.が含まれています。実際、テストのために.のみが含まれるように変更しました。

どうすれば解決できますか?ありがとう!


環境

以下の提案された解決策の多くは、私にはうまくいきません。人々がテキストの海で溺れることのないように、できるだけ焦点を絞って簡潔な質問を抽出しようとしましたが、明らかに背景をもっと提供する必要があります。

私はgitからクローンしたパッケージで開発しようとしています。元のパッケージgit-multimailは、Linuxの一部のバリアントで開発されました(私はUbuntuと推測しています)。 できるだけ変更せずにMacOSXでそれとそのテストスイートを使用できるように変更しようとしています。提案されたソリューションのいくつかが理想的でない理由は次のとおりです。

  1. rootとして、/ usr/bin /にpython2シンボリックリンクを作成します。これを必要としないソリューションを探しています。これは最初は明らかなオプションでしたが、ホストシステムをできるだけ変更しないソリューションが欲しいです。これが、現在の作業ディレクトリに一時的なシンボリックリンクを作成し、CWD(つまり.)をパスに追加し、終了時にこれを破棄したい(つまり、シンボリックリンク)理由です。

  2. pythonスクリプトを既存のpythonで呼び出すラッパースクリプトを作成します。これに関する問題は、テストスイートの多くが実際のscript_filesを実行可能ファイルとして使用することです。正しい実行環境を見つけるためのシバン。これは、テストスイートを大幅に編集することを意味します。このコンテキスト(テストフレームワークのスニペットについては以下を参照)では、すべての.pyファイルにラッパーを追加する必要があります。さらに、ユーザー/開発者は、使用しているシステムに応じてパッケージを使用するためのさまざまなルールに注意する必要があります(つまり、MacOSXでは、pythonファイルを呼び出さずに使用しないでください)ラッパー経由または明示的に/usr/bin/python file.py)を呼び出します。

    #! /bin/sh
    
    D=$(cd $(dirname "$0") && pwd)
    MULTIMAIL="$D/../git-multimail/git_multimail.py"
    POST_RECEIVE="$D/../git-multimail/post-receive"
    
    TESTREPO=$("$D/create-test-repo")
    
    HOME="$D"
    XDG_CONFIG_HOME="$D"
    GIT_CONFIG_NOSYSTEM=1
    export HOME XDG_CONFIG_HOME GIT_CONFIG_NOSYSTEM
    
    cd $TESTREPO
    
    test_email() {
        REFNAME="$1"
        OLDREV="$2"
        NEWREV="$3"
        echo "$OLDREV" "$NEWREV" "$REFNAME" | USER=pushuser "$MULTIMAIL"
    
    } 
    
  3. pythonへのすべてのpython2参照の変更 READMEはこれを示唆していますが、システムが変更を認識しているため、バージョン管理は事実上役に立たなくなります新しいバージョンとして、実際には(意味的に)ない場合。

私は(3)を使用していますが、より良い解決策を見つけようとしています。私はこれが正しい方法であることを受け入れます(つまり、「python2」を/usr/bin/pythonにポイントする適切な方法はありません。これは、テストスイートと実際のフレームワークに多くの変更を加えることなく、移植可能で目立たないものです) 。

12
Avery Chan

シンボリックリンクを解決(または調査)する必要がある場合は、プラットフォームに依存しないbashライブラリ 'realpath-lib'を使用できます。デフォルトでは、readlinkをエミュレートし、MacまたはUnixで動作します。 Github または Bitbucket にあり、無料です。

しかし、ローカル(作業)ディレクトリーから(./python2ではなく)python2を実行したいようです。 .bashrcのエイリアスを使用してこれを実行できる場合があります。そうでない場合は、PATH環境変数に作業ディレクトリ(シンボリックリンクを含む)を追加する必要があります。これは、現在のセッションのみ、または.bashrcファイル内で行うこともできます。これは、特定のユーザーのためのソリューションである可能性があります。

すべてのユーザーに対して機能する別のオプションは、/ usr/bin/pythonへのpython2シンボリックリンクをパスの別のディレクトリ、たとえば/ usr/local/binに作成することです。おそらく次のようなものです:

Sudo ln -s /usr/bin/python /usr/local/bin/python2

次に、すべてのユーザーまたはスクリプトがpythonまたはpython2コマンドを見つけます。もちろん、このオプションをインストールするには、管理者(root)権限が必要です。

2
AsymLabs

同じプログラムの複数のバージョンを管理し、切り替えるためにAppleのシステムを危険にさらしていると思います。 python2という名前の次のスクリプトを使用すると、エレガントではありませんが問題なく目的の機能を実行できます。

#!/bin/bash
exec /usr/bin/python "$@"

それを実行可能(chmod +x python2)にすると、あなたは仕事に取り掛かります。

問題の説明:

/usr/bin/pythonを実行すると、同じディレクトリでpython2.7を見つけて実行します。シンボリックリンクは、システムが/usr/binへのシンボリックリンクをたどるので失敗し、が見つかりませんpython2があります。シンボリックリンクの代わりに「ハードリンク」を使用すると、さらに一歩先を行くことができます。

rm python2
ln /usr/bin/python python2

今、従うべきシンボリックリンクはなく、同じファイル(inode)に対する2つのファイル名だけです。しかし今、私は次のメッセージで失敗します:

python2: posix_spawn: /Users/alexis/.../python22.7: No such file or directory

python22.7に注意してください:フレームワークは、作成した名前に2.7を追加しています!これを解明し、その期待に一致するリンクのフォレストをセットアップする代わりに、バージョン管理フレームワークの邪魔にならないように滞在し、上記の解決策を使用することをお勧めします。

PS。より良い解決策があるかもしれません:あなたが最初に何をする必要があるかを説明するなら(なぜpython2pythonのエイリアスとして提供する必要があるのですか)、誰かがおそらく別の方法であなたを助けることができます。これは、stackexchange言語では「XY問題」として知られています...

17
alexis

試してください:

ln -s /System/Library/Frameworks/Python.framework/Versions/2.7/bin/python2.7 /usr/local/bin/python2
5
Liangmin Li

@alexisの回答に関連して、_/usr/bin_のpythonバージョンは実際のpythonではありません。

これは、次の3つの方法で明らかになります。

  1. 発生しているエラーは、pythonが通常生成するエラーではありません。 pythonの動作は、別のpythonを探すことではなく、pythonスクリプトを実行することです。

  2. _/usr/bin/python_のシャサムと実際に実行されるpython2.7を計算する場合:

_shasum /usr/bin/python
3782d9ab14b35037c9c7fb665439a5fa695c54a6  /usr/bin/python
_
_shasum /usr/bin/python2.7
476fa96c80ac26a85b2d3b01ddfd19e513660c2c  /usr/bin/python2.7
_

それらは完全に異なります。さらに、ファイルサイズは〜20kバイト異なります。

_ll /usr/bin/python
-rwxr-xr-x  1 root  wheel  66880 May 17  2019 /usr/bin/python
_

vs.

_ll /System/Library/Frameworks/Python.framework/Versions/2.7/bin/python2.7
-rwxr-xr-x  1 root  wheel  43104 May 17  2019 /System/Library/Frameworks/Python.framework/Versions/2.7/bin/python2.7
_
  1. 最後に、python2.7とpythonを逆コンパイルして、シンボルを調査できます。ただし、これは「osxでpython2.7をpython2にシンボリックリンクする方法」の範囲を少し超えています。

したがって、(エラーが示すように)_/usr/bin/python_は向きを変えて_/usr/bin/python2.7_を探します。

_ll /usr/bin/python2.7
lrwxr-xr-x  1 root  wheel  75 Jul  1  2019 /usr/bin/python2.7 -> ../../System/Library/Frameworks/Python.framework/Versions/2.7/bin/python2.7
_

これが、以下が機能する理由です(礼儀@ liangmin-liの回答):

_    ln -s /System/Library/Frameworks/Python.framework/Versions/2.7/bin/python2.7 /usr/local/bin/python2
_
1
smaudet

Unixコマンドreadlinkを使用して、リンクの物理パスを見つけることができます。

次のリンクがあるとします。

$ ls -l /usr/bin/etags
lrwxrwxrwx. 1 root root 29 Dec 10 22:56 /usr/bin/etags -> /etc/alternatives/emacs.etags

$ ls -l /etc/alternatives/emacs.etags
lrwxrwxrwx. 1 root root 20 Dec 10 22:56 /etc/alternatives/emacs.etags -> /usr/bin/etags.ctags

$ ls -l /usr/bin/etags.ctags
lrwxrwxrwx. 1 root root 5 Dec 10 22:56 /usr/bin/etags.ctags -> ctags
  1. シンボリックリンクが指す値を見つけるには

    $ readlink /usr/bin/etags
    /etc/alternatives/emacs.etags
    

    注:上記の結果は別のリンクである可能性があります。これを解決するには、以下の#2を参照してください。

  2. シンボリックリンクが指す値の絶対パスを見つけるには

    $ readlink -f /usr/bin/etags
    /usr/bin/ctags
    
0
slm

わかりません。ラッパーlinkは問題ないが、ラッパーscriptは問題ないと思いますか?どちらも単なる間接参照のレベルです。また、特定のディレクトリからのみ呼び出すようにユーザーに指示する必要はありませんか?

いずれの場合でも、$PATHで現在の作業ディレクトリを取得できます。

 echo "echo \"Hi! I'm python\"" >|./python 
 chmod +x ./python 
 PATH="${PWD}:${PATH}" 
 python

 #OUTPUT#
 Hi! I'm python

 rm python 
 python -V 
 ln -s /usr/bin/python2 ./python 
 python -V

 #OUTPUT#
 Python 3.4.0
 Python 2.7.6

 PATH="${PATH#"${PWD}:"}" 
 python -V

 #OUTPUT#
 Python 3.4.0

入手してください。あなたの$PATHのうち。それは恐ろしい考えです。

0
mikeserv