エラーが発生しないように、このコードをどのように変更できますか?つまり、xargs
stdoutが空の場合、それ以降のコードは実行されません。
端末:
$ 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
の出力には使用しないでくださいfind
。xargs
デフォルトでは、入力パラメータはコマンド出力を持たない形式で区切る必要がありますが、もちろんそうではありませんfind
。また、出力を安定してfind -print
後処理することはできません。
find
一種の宗教的に使用する唯一の方法は、非標準拡張(もともとはGNU /から来ていますが、現在は他の多くの実装で見つかりました)をxargs
使用することです。-print0
-0
find
xargs
GNUには、入力が空の場合、コマンドを実行しない/拡張もxargs
あります(NetBSDなどの一部の実装ではデフォルトでこれを行います)。-r
--no-run-if-empty
xargs
したがって、ここでは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*'
探してください。ファイル名(パスの最後のコンポーネント)だけを見つけることに置き換えてください)bar
grep 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を除く)xargs
。xargs
cmd
完全性のために
... | xargs -I {} cmd {}
cmd
入力が空であっても空であっても実行されません。この場合、入力を引数に分割することは異なります。先頭のスペースは削除され、引用符はまだxargs
一意の方法で処理されますが、そうでない場合、引数はスペースで区切られた単語ではなく完全な行です。