空のstdoutを無視するように "xargs"に指示する方法は? [コピー]

空のstdoutを無視するように

エラーが発生しないように、このコードをどのように変更できますか?つまり、xargsstdoutが空の場合、それ以降のコードは実行されません。

端末:

$ cat << EOF > dummy.sh
#! /usr/bin/env bash
[[ -f "\$1" ]] &&  echo "file=\$1" || { echo "error"; exit 1; } 
shift 
(( \$# == 0 )) || "\$0" "\$@" 
EOF
$ chmod +x dummy.sh
$ mkdir trash.later && touch trash.later/foo
$ find trash.later -type f | xargs -n 1 ./dummy.sh 
file=trash.later/foo
$ find trash.later -type f | grep 'bar' | xargs -n 1 ./dummy.sh 
error

ベストアンサー1

xargsの出力には使用しないでくださいfindxargsデフォルトでは、入力パラメータはコマンド出力を持たない形式で区切る必要がありますが、もちろんそうではありませんfind。また、出力を安定してfind -print後処理することはできません。

find一種の宗教的に使用する唯一の方法は、非標準拡張(もともとはGNU /から来ていますが、現在は他の多くの実装で見つかりました)をxargs使用することです。-print0-0findxargs

GNUには、入力が空の場合、コマンドを実行しない/拡張もxargsあります(NetBSDなどの一部の実装ではデフォルトでこれを行います)。-r--no-run-if-emptyxargs

したがって、ここではGNU find//xargsまたはgrep互換デバイスを使用して次のことができます。

find trash.later -type f -print0 |
  grep -z bar |
  xargs -r -0 -n 1 ./dummy.sh

しかし、これは標準と比較して利点を提供しない。

find trash.later -path '*bar*' -type f -exec ./dummy.sh {} ';'

(あなたが望むように、ファイルパスのどこにでも-path '*bar*'探してください。ファイル名(パスの最後のコンポーネント)だけを見つけることに置き換えてください)bargrep bar-name '*bar*'bar

より多くの関連情報については、以下をお読みください。検索結果を繰り返すのはなぜ悪い習慣ですか?


あなたの質問に対するより一般的な答えでxargsサポートされていない-r実装の場合、回避策はラッパーを--no-run-if-empty使用することです。sh

変える:

... | xargs -n1 cmd

する:

... | xargs sh -c 'for file do cmd "$file"; done' sh

入力がない場合は引き続き実行されますが、引数リストが空shであるため、ループに渡された項目がないためcmd実行されません。

ifne入力が空でない場合にのみコマンドを実行するコマンドも参照してください。moreutils

... | ifne xargs -n1 cmd

ただし、入力が空でなく空行のみを含む場合はifne実行されますが、その入力はまだ引数がないと見なされ、引数なしで一度だけ実行されます(NetBSDを除く)xargsxargscmd

完全性のために

... | xargs -I {} cmd {}

cmd入力が空であっても空であっても実行されません。この場合、入力を引数に分割することは異なります。先頭のスペースは削除され、引用符はまだxargs一意の方法で処理されますが、そうでない場合、引数はスペースで区切られた単語ではなく完全な行です。

おすすめ記事