質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.92%

xargsとパイプの違いについて

受付中

回答 4

投稿

  • 評価
  • クリップ 1
  • VIEW 4,997

hirhir

score 11

xargsとgrepの違いについてよくわからないので教えてください。
例えば、カレントディレクトリにa.txt, b.txtが存在しているとします。
(OSはmacOSで試しています。)

その状態で、パイプを使用してfindとrmを繋ぐと、上手くいきません。

$ find . -regex .*[a-z]\.txt | rm -v
usage: rm [-f | -i] [-dPRrvW] file ...
       unlink file

一方でxargsを使用してrmの引数にfindの結果を加えると、上手くいきます。

$ find . -regex .*[a-z]\.txt | xargs -t rm -v
rm -v ./a.txt ./b.txt
./a.txt
./b.txt

私の理解は以下です。おそらく何か大きな勘違いしているのだと思います。。。

ー私の理解ーーーーーーーーーーーーーーーーーーーーーーーーーーー
rmを普段使う時って、標準入力から削除対象のファイル引数として渡しますよね。。なので、パイプでfindのstdoutをrmのstdinに繋いであげれば、findの結果出力されたファイル群を削除してくれるはず。。。
ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー

xargsやパイプの仕組みに詳しい方、教えて頂けないでしょうか??

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 4

+3

rmを普段使う時って、標準入力から削除対象のファイル引数として渡しますよね。

これが、大きな間違いです。今までrmを使ったことが無い??
削除対象ファイルはコマンドラインで与えます。
例:rm foo
rmは標準入力を読みません。

追記

書きぶりから、rmコマンドを使ったことがないとは思えないので、コマンドラインと標準入力の言葉の区別が付いていないと言うことですかね。
echo・・・コマンドライン引数を標準出力に出力する
cat・・・(コマンドライン引数無しでcatコマンドを起動した場合)標準入力から入力して標準出力に出力する
で、分かりますでしょうか?

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

+1

簡単な説明ですが、例えば、パイプの場合とxargsの違いは、
(1)rm
echo file1 file2 | rm       ---はNGですが
echo file1 file2 | xargs rm ---はOKです。

(2)cat
echo file1 file2 | cat       ---はOKです
echo file1 file2 | xargs cat ---もOKです

rmとcatの違いは、stdinを入力としているかいないがです。

(1)を書き換えた場合下記と同じ動きになります。
rm <(echo file1 file2)  --はNGです。
rm file1 file2  --はOKです。

(2)catの場合stdinがない場合は、パラメータの指定ファイルをオープンします。
cat <(echo file1 file2)  --はstdinでOKです。
cat file1 file2  --はファイルでOKです。
但し、上記は”file1 file2”の文字列が出力され
下記は、file1 file2の内容がコンカチされて出力されます。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

otnさんと同じく質問者さんはパイプ(標準入力)と引数を勘違いなさっていると思いますので私は補足までに

xargsは「標準入力を引数に変換」してくれるものです。

例えば、echo a | echoとしてもなにも起きません。
しかし、echo a | xargs echoとするとaが表示されます。これはxargsが(xargsの引数) (標準入力)にコマンドを変換して実行します。

分かりづらければ、プログラムの話をすると、引数はc言語ではargs[]で取ります(正確にはmain関数の第2引数ですがそれは理解のために省略)

一方、標準入力はc言語ではstdinという変数を使ってfread(str, 256, 1, stdin)のように読み込みます。

つまり、標準入力とプログラムの後ろにつく引数は全く別物なんです。
パイプで渡されるものは、パイプの前の標準出力であり、パイプの後ろのコマンドには標準入力にその値が渡ります。
パイプの前後の引数と標準入出力は何の関係もありません。本来、何の関係もない標準入出力を引数に展開してくれるのがxargsというわけです。

ただ、UNIXのコマンドは往々にして標準入出力を引数のように扱ってくれるコマンドがありますから(headとかtailとか)、勘違いされるのも仕方ないかなと思います。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

私もパイプとxargs、コマンド引数と標準入力に関して混乱していたので以下に私の理解をまとめます。

  • コマンド引数   :  コマンドの右側に書いてそのコマンドに与える文字や数値。

  • 標準入力     : そのコマンドへの入力元。コマンド引数とはまた別物。通常は端末。

  • 標準出力     : そのコマンドの出力先。通常は端末。

  • リダイレクション : そのコマンドの標準入出力を<,>で指定する。指定なしだと端末。
    例(出力)% pwd > fileA.txt
    例(入力)% cat < fileA.tx

  • パイプ      : 2つのコマンドの標準出力(>)と標準入力(<)を同時にした物。
    例)% pwd | cat
    注意)>はパイプではなく出力先の指定。なので以下ではcatと言うファイルができる。
    % pwd > cat

  • xargs        : その標準入力を引数で指定したコマンドの引数にしてして実行。
    例)% pwd | xargs grep ABC
    % grep ABC pwdとしたのと一緒。

  • cat,head,tail, ls等  : 引数と標準入力両方同じ様に取れる。
    例)% cat fileA.txt
    % cat < fileA.txt

  • rm, echo等      : 引数のみ取れる。標準入力なし。
    例(O.K)% rm fileA.txt
    例(N.G)% rm < fileA.txt

なので標準入力がないrmにパイプを使うのはN.Gです。rmを使うには引数を指定する必要があります。xargsを使えばxargsの標準入力をrmの引数にして実行してくれます。

% echo fileA.txt | rm      引数がないのでN.G
% echo fileA.txt | xargs rm  xargsがecho fileA.txtの結果をrmの引数にしてくれるのでO.K

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.92%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る