私は別のスクリプトで実行可能ファイルを使用していましたが、/usr/bin/foo
少し奇妙に動作していたので、同じファイル名を持つBashラッパーを作成し、/usr/local/bin/foo
その中で誤った動作を修正しました。私のPATH
もの/usr/local/bin:/usr/bin
。ラッパースクリプトでは、無限ループに陥らないように絶対パスを介して元の実行可能ファイルを実行する必要があります。
$ cat /usr/local/bin/foo
#/bin/zsh
/usr/bin/foo | grep -v "^INFO" # reduce output
foo
next inを実行する簡単な方法(おそらくZshまたはBash固有)はありますかPATH
?つまり、 current が実行されるディレクトリの次のディレクトリでfoo
元の実行ファイルの絶対パスを使用する必要はありませんか?PATH
foo
私はそれのための関数を作ることができます/etc/zshenv
。あまりありません。もし基準があるのか知りたいです。エイリアスを使用したり、元の実行可能ファイルを回復したくありません。
編集 1: = $ cat /usr/local/bin/foo #/bin/zsh path=(${path/#%$0:A:h}) foo | grep -v "^INFO" # 出力を減らす
これにより、現在の実行可能ファイル()の絶対()ディレクトリ()と正確に一致する()PATH()の${path/...}
すべての文字列が消去されます(ただし保存されます)。正直言って、StackExchangeで組み立てましたが、完全には理解していませんでした。私はそれが私を噛まないことを願っています。#%
:A
:h
$0
編集2:
$ cat /usr/local/bin/foo
#/bin/zsh
path[${path[(i)$0:A:h]}]=() foo | grep -v "^INFO" # reduce output
$path[(i)foo]
foo
配列のインデックスを検索するpath
か、1に配列長を加えた値を見つけます。
答え1
スクリプトがあるディレクトリ($0:h
zsh、"${0%/*}"
in sh)を見つけて、そのディレクトリから削除できますPATH
(path=(${path:#$0:h})
zsh、shでもっと複雑。同じディレクトリが2回含まれている場合PATH
(たとえば、シンボリックリンクを介して)、この操作は失敗する可能性があります。
直接アプローチの欠点は、パスからディレクトリが削除されるが、同じディレクトリにある他のプログラムが理想的である可能性があることです。パスの検索に変更されたパスのみを使用すると、この問題を解決できます。
next=$(path=(${path:#$0:h}); print -lr -- =$0:t)
$next
代わりにPATH
手動で照会を実行し、実行中のスクリプトをスキップします。
for d in $path; do
if [[ -x $d/$0:t && ! $d/$0:t -ef $0 ]]; then
exec $d/$0:t
fi
done
答え2
例:カスタムエイリアスと実際のコマンドを印刷するには、
$ HOME / bin /に別のコマンドを追加すると、順番にエイリアスが表示され、その後にPATH付きのエントリが表示されます。同じ順序。type -a egrep
egrep
egrep
$CD#家に帰る $mkdir -p 空 $PATH=$HOME/bin:$PATH $type-a egrep egrepのエイリアスは `egrep --color = auto'です。 egrep は /bin/egrep です。 $ echo -e >bin/egrep '#!/bin/bash\necho TEST' $ chmod 755 bin/egrep $type-a egrep egrepのエイリアスは `egrep --color = auto'です。 egrepは/home/$USER/bin/egrepです。 egrep は /bin/egrep です。 # /home になくエイリアスでもない唯一の項目だと確信していると仮定 $タイプ-a egrep | grep -Ev '/home|alias' |cut -d''-f3 /bin/egrep $rm $HOME/bin/egrep
答え3
次のことができます。
#! /bin/zsh -
# find the other occurrences of a command with the same name in $path that
# are a different file
other_mes=(
${^path/#%/.}/$0:t(N*^e['[[ $REPLY -ef $0 ]]'])
)
if (( ! $#other_mes )) {
print -ru2 Could not find any other $0:t in PATH.
exit 1
}
# run the first found
$other_mes[1] "$@" | grep -v '^INFO'
# return the exit status of the other me, not of grep
exit $pipestatus[1]
${path/#%/.}
$path
空の要素を次に置き換えます。.
$0:t
:尾(基本名)$0
[[ a -ef b ]]
a
b
とが同じファイルへの2つのパスであるため、シンボリックリンクの確認後に同じファイルであることが確認された場合はtrueを返します(たとえば、またはへのシンボリックリンク、または互いへのハードリンクまたはシンボリックリンクのためvs/usr/bin/foo
)。/bin/foo
/bin
/usr/bin
../bin/foo
$PWD
/usr/local
/usr/foo/../bin/foo
sh
構文(および最もサポートされている実装)を使用し[
て改行文字で終わらないと仮定すると、次のようになります。-ef
$0
#! /bin/sh -
other_me=$(
me=$(dirname -- "$0")
IFS=:; set -o noglob
for dir in $PATH''; do
other_me=${dir:-.}/$me
if [ -x "$other_me" ] && [ -f "$other_me" ] && [ ! "$other_me" -ef "$me" ]; then
printf '%s\n' "$other_me"
exit
fi
done
printf>&2 '%s\n' "Cound not find any other $me in PATH."
exit 1
) || exit
{
exit_status=$(
{
{
"$other_me" "$@" 4>&-
echo "$?" >&4 4>&-
} 3>&- | grep -v '^INFO' >&3 3>&- 4>&-
} 4>&1
)
} 3>&1
exit "$exit_status"
末尾の複合ビットによって取得された終了状態です$other_me
。