web-dev-qa-db-ja.com

フルパスを指定せずにBashビルトインの代わりにシステムコマンドを使用する

私はインタラクティブシェルとしてBashを使用していて、Bashがシェルビルトインコマンドの代わりにシステムコマンドを実行する簡単な方法があり、両者が同じ名前を共有している場合に疑問に思っていました。

たとえば、システムkillutil-linuxから)を使用して、シグナルを送信する代わりに、名前付きプロセスのプロセスID(pid)を出力します。

$ /bin/kill -p httpd
2617
...

システムコマンドのフルパスを指定しない場合、システムコマンドの代わりにBashビルトインが使用されます。 killビルトインには-pオプションがないため、コマンドは失敗します。

$ kill -p httpd
bash: kill: p: invalid signal specification

シェル組み込みではなく外部の「time」コマンドを使用するようにする に記載されている回答を試してみましたが、timeが実際にはシェルであるため、それらのほとんどが機能しますkeyword–シェルではないbuiltin.

enable -n killを使用してBashビルトインを一時的に無効にする以外に、これまでに見てきた最善の解決策は次のようにすることです。

$(which kill) -p httpd

Shellビルトインの代わりに外部コマンドを実行する他のより簡単な(少ない入力を伴う)方法はありますか?

killは単なる例であり、 generalized ソリューションがcommandビルトインの接頭辞を付けて実行される外部コマンドと同じ名前。ほとんどの場合、私は通常、組み込みバージョンを使用することを好みます。これは、新しいプロセスの分岐を節約し、場合によっては組み込みコマンドに外部コマンドにはない機能があるためです。

18

envがパスにあると仮定します:

env kill -p http

envは、(おそらく)変更された環境で、最初の引数で指定された実行可能ファイルを実行します。そのため、Shellビルトインコマンドを認識していないか、動作しません。

これにより、シェルジョブコントロールの残骸が生成されますが、外部コマンドには依存しません。

exec kill -p bash &

execは、現在のシェルを置き換えるために実行可能ファイルを必要とするため、組み込みを使用しません。ジョブはバックグラウンドで実行されるため、現在のシェルではなく、フォークされたバックグラウンドシェルを置き換えます。

21
chepner

あなたが望むことをする最も簡単な方法は、行を置くことかもしれません

alias kill="/bin/kill"

~/.bashrcファイルに。その後、bashの新しいログイン/呼び出しごとに、「kill」が/bin/killとして解釈されます。

1
Benjamin Staton

この非常に特殊なケースでは、コマンドpgrepはニーズに完全に一致します。

一般的な意味では、関数は機能します。 「ファイルコマンド」から:

fcmd(){ local a=$1; shift; $(which "$a") "$@"; }

呼びます

fcmd kill -p httpd

しかし、入力が少なくて済むのであれば、良いエイリアスよりも短い方法はありません。

「リストpid」(lp)の概念から:

alias lp='/bin/kill -p'

次に、次のように入力します。

lp httpd
1
user79743

いくつかのタイピングを必要とするソリューションを知っていて、より少ないタイピングを必要とするソリューションが必要な場合は、それをビルドします。

runFile() { local cmd="$1"; shift; cmd="$(which "$cmd")" && "$cmd" "$@"; }

通常ある程度の労力を必要とするものを短縮することは、コンピュータが優れていることです。

1
PSkocik

(zshの場合)コマンド名の前に=記号を付けて、組み込みではなくシステムバージョンを取得できます。これは、特定のシナリオを混乱させるエイリアスを回避するための便利な方法でもあります。

$ =kill -p httpd
0
Caleb