cmd2 `cmd1` vs cmd1 | xargs cmd2

J'essaie de find un file avec find et ensuite passer le path trouvé à sqlite3 . Je suis seulement tombé dans l'invite sqlite> si ma command est de la forme:

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

Mais ces forms ne fonctionnent pas:

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

Pourquoi ces commands ne font-elles rien?

Dans:

 ... | xargs cmd 

en fonction de l'implémentation, le stdin de cmd est soit /dev/null soit ce canal. Il ne peut pas être le stdin externe puisque cela est perdu à cause de la tuyauterie.

 $ 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] 

Dans les deux cas, sqlite3 ne pourra pas lire vos commentaires.

Le:

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

command prend la première ligne du premier path de file returnné par find , le divise en fonction de $IFS , effectue le globbing sur ceux-ci et transmet les mots résultants en arguments différents à sqlite3. Cela n'a pas beaucoup de sens.

Avec GNU find (probablement ce que vous utilisez depuis que vous utilisez -iname ):

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

Nous utilisons -exit pour dire find pour quitter après avoir imprimé le premier file trouvé. Nous utilisons la forme moderne de substitution de command $(...) , et sautons la partie split + glob (ce qui n'a pas de sens) en citant la substitution de la command.

Vous pouvez également utiliser (encore GNU spécifique):

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

(bien que vous sqlite3 statut de sortie de sqlite3 ).

Avec zsh :

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