コマンドを直接実行することと「bash -c」を使用することの違いは何ですか?

コマンドを直接実行することと「bash -c」を使用することの違いは何ですか?

bash -cコマンド(組み込みまたは外部)の場合、bashシェルプロセスで直接実行することとbashシェルで実行することの違いは何ですか?互いに比較すると、どのような長所と短所がありますか?

For example, in a bash shell, run `date` directly, and run `bash -c
date`. Also consider a builtin command instead of an external one.

答え1

  1. この-cオプションを使用すると、プログラムはコマンドを実行できます。分割して実行するのははるかに簡単です。

    execl("/bin/sh", "sh", "-c", "date | od -cb  &&  ps > ps.out", NULL);
    

    フォークと比較すると、パイプを作成し、再フォークし、execl各サブパイプラインを呼び出し、呼び出し、終了wait状態を確認し、再フォークし、呼び出し、close(1)ファイルを開き、ファイル記述子1で開いていることを確認してから、他のexecl。私はこれがこのオプションが当初作られた理由だと思います。

    ライブラリsystem()関数は上記のようにコマンドを実行します。

  2. ランダムに複雑なコマンドを受け入れ、それを単純なコマンドのように見せる方法を提供します。これは、カスタムコマンド(たとえば、または)を実行するプログラムにfind … -exec役立ちますxargs。しかし、あなたはこれがあなたの質問に対する答えの一部であることをすでに知っていました。 複合コマンドを他のコマンドの引数として指定するには?
  3. これは、 bash ではなく対話型シェルを実行する場合に便利です。代わりにbashを実行している場合は、この構文を使用できます

    $ash-c"注文する
     
    $csh -c"注文する
     
    $ダッシュ-c"注文する
     
    $zsh -c"注文する

    すべてのシェルもこの-cオプションを認識するため、別のシェルでコマンドを実行してください。もちろん、次のような結果が得られます。

    $再
    再$注文する
    グレー$出口
     
    $csh
    csh$注文する
    csh$ 終了
     
    $ダッシュ
    ダッシュ$注文する
    ダッシュ$exit
     
    $ジッシュ
    zsh$注文する
    zsh$ 終了

    私はash$ 他のシェルプロンプトを説明するためになどを使用します。実際にはこれを得ることができないかもしれません。

  4. たとえば、「新しい」bashシェルでコマンドを実行したい場合に便利です。

    $ ls -lA
    total 0
    -rw-r--r-- 1 gman gman   0 Apr 14 20:16 .file1
    -rw-r--r-- 1 gman gman   0 Apr 14 20:16 file2
    
    $ echo *
    file2
    
    $ shopt -s dotglob
    
    $ echo *
    .file1 file2
    
    $ bash -c "echo *"
    file2
    

    または

    $ type shift
    shift is a shell builtin
    
    $ alias shift=date
    
    $ type shift
    shift is aliased to ‘date’
    
    $ bash -c "type shift"
    shift is a shell builtin
    
  5. 上記は誤解を招く過度に単純化された内容です。 bash の実行時に-c考慮されます。非対話型~/.bashrcシェルであり、指定しない限り読みません-i。だから、

    $タイプCP
    cp のエイリアスは「cp -i」です。          #定義済み~/.bashrc
     
    $cp .file1 ファイル 2
    cp:"file2"を上書きしますか? N
     
    $ bash -c "cp .file1 ファイル2"
                                      #既存のファイルを確認せずに上書きしました!
    $ bash -c -i "cp .file1 ファイル2"
    cp:"file2"を上書きしますか? N

    代わりに-ci-i -cまたはを使用できます。-ic-c -i

    これは、3段落に記載されている他のシェルにもある程度適用される可能性があるため、長い形式(つまり、実際に入力とまったく同じ量の2番目の形式)がより安全になります。特にinit / configファイルを設定した場合はさらにそうです。その皮。

  6. 〜のようにワイルドカードの説明、新しいプロセスツリー(新しいシェルプロセスと可能なサブプロセス)が実行されているため、サブシェルで環境が変更されます。 できない親シェル(現在のディレクトリ、環境変数の値、関数定義など)に影響します。したがって、sh -cに埋め込まれたシェルが親シェルによって開始されたバックグラウンドタスクに影響を与えたり、アクセスできなかったり、それを待つことができないことを想像することは困難です。本質的にただ実行するのと同じです。fgbgjobswaitsh -c "exec some_program"some_program対話型シェルから直接一般的な方法です。  sh -c exitそれは大きな時間の無駄です。  ulimitまた、umask子プロセスのシステム設定を変更した後、実行せずに終了することも可能です。

    コンテキストで動作するほとんど唯一の組み込みコマンドsh -cはですkill。もちろん、出力(echo、、printfおよびpwd)のみを生成するコマンドtypeは影響を受けず、ファイルに書き込んでも持続します。

  7. もちろん、組み込み機能を使用することもできます。これと組み合わせる たとえば、外部コマンド
    sh -c "CDディレクトリ;プログラム
    ただし、通常のサブシェルを使用すると、本質的に同じ効果が得られます。
    (CDディレクトリ;プログラム)
    どちらがより効率的ですか?同様のことについても同じです(2つの部分)。
    sh -c "umask 77;プログラム
    またはulimit(またはshopt)。その後に任意に複雑なコマンドを入れることができるので(フルシェルスクリプトの複雑さまで)、、、、、などの組み込み-cコマンドを使用できます。sourcereadexporttimessetunset

答え2

実行bash -c "my command here"と単に実行の主な違いmy command hereは、前者はサブシェルを起動し、後者は現在のシェルでコマンドを実行することです。

組み込みコマンドと外部コマンドは実際には重要ではありません。何もない現在のシェルまたはサブシェルで実行できます。

しかし、効果には多くの違いがあります。

  • サブシェルの環境変更できない親シェル(現在のディレクトリ、環境変数の値、関数定義など)に影響します。
  • 親シェルに設定されているがエクスポートされない変数は、サブシェルでは使用できません。

これは、完全な違いのリストからは遠いですが、重要な点をカバーしています。bash -c;元のシェルとは異なるプロセスです。

サブシェルを作成すると、パフォーマンスが低下する可能性があります。これは、スクリプトが頻繁に実行される場合、またはコマンドがある種のループ内にある場合に最も関連性があります。

答え3

-c オプションは、デフォルトではファイルではなく CLI 引数として提供されるミニシェルスクリプトを実行します。

$ bash -c the_script the_scriptname 1 2 3 

実際には次のようになります。

$ echo the_script > the_scriptname
$ bash the_scriptname 1 2 3
$ rm the_scriptname

ご覧のとおり:

$ bash -c 'printf " ->%s\n" $0 "$@"; echo $-;' scriptname 1 2 3
   ->scriptname
   ->1
   ->2
   ->3
  hBc

(英語:$ 0 ==スクリプト名; $@ ==(1 2 3); bashは次のことを行います。 時間再注文の履行第二民族拡張と既に-c旗を持って走っている)

そして:

 $ echo 'printf " ->%s\n" $0 "$@"; echo $-;' > scriptname
 $ bash scriptname 1 2 3 
 ->scriptname
 ->1
 ->2
 ->3
 hB

答え4

-c文字列

-c オプションがある場合は、文字列からコマンドを読み込みます。文字列の後にパラメータがある場合は、$ 0から始まる位置パラメータに割り当てられます。

私はこれがあなたの問題を解決すると思います

関連情報