以下のテストでファイルが存在しないと表示されるのはなぜですか?

以下のテストでファイルが存在しないと表示されるのはなぜですか?

一方

$ PSEXE="$(whereis ps)" 
$ echo $PSEXE
ps: /nix/store/06sa9q0xmd3rhqbd0pb5kpdhz68vq2pk-system-path/bin/ps
$ file  /nix/store/06sa9q0xmd3rhqbd0pb5kpdhz68vq2pk-system-path/bin/ps
/nix/store/06sa9q0xmd3rhqbd0pb5kpdhz68vq2pk-system-path/bin/ps: symbolic link to /nix/store/1mhhpcb9dxyila8jqa3x1cqj9nd3l4sg-procps-3.3.16/bin/ps

以下のテストでファイルが存在しないと表示されるのはなぜですか?

$ if [ ! -x "$PSEXE" ]
> then
> echo yes
> fi
yes

ありがとうございます。

答え1

スクリプトを分解してみましょう。

PSEXE="$(whereis ps)" 
echo "$PSEXE"

私のシステムでは、これはあなたのシステムと非常によく似た形式を返します。続行できます。

ps: /bin/ps

特に変数に$PSEXE文字列が含まれていることに注意してくださいps: /bin/ps

その後、条件式を使用してスクリプトを取得できます。

if [ ! -x "$PSEXE" ]

シェルはこれを次のように効果的に評価します。

if [ ! -x 'ps: /bin/ps' ]

ファイルが存在しないため、ps: /bin/ps実行可能なテストが失敗し、否定が適用され、結果の式はと評価されますtrue


実行可能ファイルがに存在することを確認するには、次のものを$PATH使用できますtype

PSEXE='ps'
if type "$PSEXE" >/dev/null 2>&1
then
    echo "Executable exists"
fi

bashターゲット実行可能ファイルを簡単に抽出できます。

PSEXE=`type -p ps 2>/dev/null`

しかし、POSIXの場合、sh状況はもう少し複雑です。

PSEXE=`type ps 2>/dev/null | sed -n 's/^[^ ]* is //p'`

関連情報