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


17

私は対話型シェルとしてBashを使用していますが、両方が同じ名前を共有している場合、Bashにシェル組み込みコマンドの代わりにシステムコマンドを実行させる簡単な方法があるかどうか疑問に思っていました。

たとえば、次のシステムを使用してkill(からutil-linux)シグナルを送信する代わりに、指定されたプロセスのプロセスID(pid)を出力します。

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

システムコマンドのフルパスを指定しないと、システムコマンドの代わりにBashビルトインが使用されます。kill組み込みは持っていない-pコマンドが失敗したように、オプションを:

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

Make bashがシェル組み込みではなく外部の `time`コマンドを使用するようにリストされている回答を試しましたtimeが、実際にはシェルキーワードであり、シェル組み込みではないため、ほとんどが機能します。

で一時的にBashビルトインを無効にする以外にenable -n kill、これまでに見た中で最良の解決策は以下を使用することです:

$(which kill) -p httpd

シェルビルトインの代わりに外部コマンドを実行する他の簡単な(タイピングが少ない)方法はありますか?

これkillは単なる例であり、組み込みコマンドをプレフィックスとして使用すると、外部コマンドと同じ名前の関数が実行されないようにする一般的なソリューションcommandが必要です。ほとんどの場合、新しいプロセスをフォークする必要がないため、組み込みバージョンを使用することを好みます。また、組み込みコマンドには外部コマンドにはない機能がある場合があります。


which killバッククォートで囲む(コメントに入れることはできません)は、少し短くなります。
abligh

@abligh良い点。私は、コマンド置換のための「新しい」ER構文を使用して自分自身を訓練年間を費やしてきました:)。
アンソニー・G -モニカのための正義の

@abligh:参考までに、バックスラッシュ(\)を前に付けることで、コメントに「バックティック」を挿入できます。しかし、に固執する理由がある$(…)-を参照して、このこの、およびこれを
G-マンは「元に戻すモニカ言う

回答:


20

envあなたのパスにあると仮定します:

env kill -p http

env(おそらく)変更された環境で、最初の引数で指定された実行可能ファイルを実行します。そのため、シェルの組み込みコマンドを認識したり、シェル組み込みコマンドを処理したりしません。

これにより、シェルのジョブ制御がいくらか生成されますが、外部コマンドに依存しません。

exec kill -p bash &

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


2
env私見では明らかに正しい答えです。
15年

@abligh:削除された回答のコメントにあなたは正しい。ではなくcommand -p cmd外部コマンドを呼び出します。zshbash
cuonglm

6
(exec kill -p http)これにより、現在のシェルの代わりにサブシェルがジョブに置き換わり、ジョブ制御の問題に対処する必要がなくなります。
マイケルホフマン

1
@AnthonyGeoghegan確かに、それenvはシェルではないので、シェルの組み込みについても知りません。niceまたは、xargsまたはそのような他のプログラムでも同じ効果が得られます。
user253751

1

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

alias kill="/bin/kill"

あなたの~/.bashrcファイルに。その後、bashの新しいログイン/呼び出しはそれぞれ「kill」をとして解釈し/bin/killます。


私はすでにエイリアスを考えていましたが、それはリンクした質問にリストされたソリューションの1つでしたが、command「シャドウ」コマンドごとに個別のエイリアスを作成するのではなく、より一般的なソリューション(ソリューションに類似)を望んでいます。これで質問を編集して、これをより明確かつ明確にしました。ほとんどの場合、プロセスはジョブIDで指定できるため、通常は組み込みバージョンを使用することを好みます。とにかくありがとう。
アンソニーG-モニカの正義

1

入力が必要なソリューションを知っていて、入力を少なくするソリューションが必要な場合は、それをビルドします。

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

通常多少の労力を要するものを短縮することは、コンピューターが得意とするものです。


1
それは良い一般的なポイントなので、あなたの答えに賛成します。過去数年にわたって、私は定期的に使用するシステムのエイリアス、関数、およびスクリプトのコレクションを構築してきました。ただし、セットアップしていない新規インストールまたはサーバーで作業することがあるため、可能な限りカスタマイズされていないソリューションを使用することを好みます。ありがとう。
アンソニーG-モニカの正義

1

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

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

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

として呼び出す

fcmd kill -p httpd

ただし、必要な入力が少ない場合は、適切なエイリアスよりも短い方法はありません。

概念「list pid」(lp)から:

alias lp='/bin/kill -p'

次に、単に入力します:

lp httpd

0

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

$ =kill -p httpd

1
Bashバージョン4.3.30で試してみましたが、うまくいきませんでした。そのような構文を見たことはありません。この機能が文書化されている場所へのリンクを追加できますか?通常、エイリアスのないバージョンのコマンドを実行するには、エイリアスの前にバックスラッシュを付けます。
アンソニーG-モニカの正義

@Anthonyたぶんこれがzsh唯一のことです。定期的に使用していますがbash、明日はコンピューターから確認します。
カレブ

私は慣れていないシェルかもしれません(bash、dash、cshにしか慣れていません)。のためにのみ機能する別の回答がありました(削除されたため)zsh。この質問にbashタイトルを付けてタイトルに使用しましたが、zshユーザーはまだ役に立つと思うので、この回答を保持する必要があります。
アンソニーG-モニカの正義

-1

あなたのkillマンページに対してバグレポートを送信し、そこから機能を取得したいときにいつでもpkill使用され、使用される非標準オプションが含まれている理由を尋ねることができますpkillpkill.

あなたが電話した場合:

pkill httpd

記述した問題を回避します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.