cmd2 `cmd1`とcmd1 xargs cmd2 |

cmd2 `cmd1`とcmd1 xargs cmd2 |

findファイルを見つけて見つけたパスをに渡そうとしますsqlite3sqlite>コマンドが次の形式を取る場合にのみプロンプトが表示されます。

sqlite3 `find . -type f -iname "*.db" | head -n1`

ただし、次の形式は機能しません。

find . -type f -iname "*.db" | head -n1 | xargs sqlite3
find . -type f -iname "*.db" | head -n1 | xargs -I% sh -c 'sqlite3 %;'

次のコマンドがまったく機能しないのはなぜですか?

答え1

存在する:

... | xargs cmd

実装に応じて、cmdstdinは/dev/nullまたは対応するパイプです。パイプを介して損失するため、外部標準入力にすることはできません。

$ echo /proc/self/fd/0 | gnu-xargs ls -ld
lr-x------ 1 me me 64 Dec 11 22:04 /proc/self/fd/0 -> /dev/null
$ echo /proc/self/fd/0 | busybox-or-solaris-...-xargs ls -ld
lr-x------    1 me me        64 Dec 11 22:04 /proc/self/fd/0 -> pipe:[99839]

どちらの場合も、sqlite3入力内容を読み取ることができません。

これ:

sqlite3 `find . -type f -iname "*.db" | head -n1`

このコマンドは、から返された最初のファイルパスの最初の行を取得してfind分割し、$IFSワイルドカードを実行し、結果の単語を別の引数としてsqlite3に渡します。これはほとんど意味がありません。

GNUを使用するfind(おそらく使用しているGNU -iname):

sqlite3 "$(find . -type f -iname "*.db" -print -quit)"

最初に見つかったファイルを印刷して終了するには、-exitTellを使用します。find我々は、現代的な形式の命令置換を使用し、$(...)命令置換を引用して、分割+glob部分をスキップします(無言)。

以下を使用することもできます(まだGNUのみ)。

find . -type f -iname '*.db' \( -exec sqlite3 {} \; -o -true \) -quit

(終了状態は消えますがsqlite3

そしてzsh

setopt extendedglob # best in ~/.zshrc
sqlite3 ./**/*.(#i)db(D.[1])

関連情報