xargs -I différence de remplacement-str

14

D'après ce que je comprends, ce qui suit devrait signifier exactement la même chose:

ls -1 | xargs file {}
ls -1 | xargs -I{} file {}

Si l'option -I n'est pas spécifiée, sa valeur par défaut est -I {}.

Je veux lister tous les fichiers du répertoire courant et lancer file commande sur chacun d'eux. Certains ont des espaces dans leurs noms. Cependant, j'ai remarqué la différence. Voir ci-dessous:

$ ls -1
Hello World
$ ls -1 | xargs file {}
{}:    ERROR: cannot open `{}' (No such file or directory)
Hello: ERROR: cannot open `Hello' (No such file or directory)
World: ERROR: cannot open `World' (No such file or directory)
$ ls -1 | xargs -I{} file {}
Hello World: directory

Si -I {} est explicitement spécifié, les espaces dans les noms de fichiers sont traités comme prévu.

foresightyj
la source
3
"Si l'option -I n'est pas spécifiée, sa valeur par défaut est -I {}", ce qui est incorrect, du moins avec GNU xargs.
jjlin
Je comprends mon erreur. Je devrais spécifier soit xargs file ou xargs -I{} file {}. Ne devrait pas être xargs file {}. Je suppose que quand spécifiant explicitement -I {}, le bash le traitera comme file "Hello World". Sans -I {}, il est traité comme file Hello World.
foresightyj
1
(1) Cette discussion a peu à voir avec le shell (bash). (2) C’est bien que vous connaissiez la -1 option de ls, mais il est activé par défaut lorsque la sortie de ls est un fichier ou une pipe, vous n’en avez donc pas besoin ici. (3) Vous confondez -I avec les obsolètes -i (minuscule I ) option. -ifoo est équivalent à -Ifoo, mais simple -i est équivalent à -I{}. Mais utiliser -I{}. (4) Si vous voulez vraiment faire ce que vous dites vouloir, pourquoi ne pas simplement dire file *?
Scott
@Scott Mon intention initiale était d'écrire `find. -name "* .mov" | xargs -I {} fichier {} `pour rechercher récursivement tous les fichiers mov et les exécuter file sur eux. Mais je suis venu avec un exemple plus simple en utilisant ls. Tu as raison. Pour ça, file * est le meilleur.
foresightyj
1
trouver a -exec.
Cristian Ciupitu

Réponses:

17

le -I nécessite un espace réservé défini. le -i l'option assumera {} est l'espace réservé. C’est là que j’ai trouvé une hypothèse de {} dans man xargs au moins sur Cygwin et CentOS.

xargs appelé sans l'une ou l'autre des options n'a pas besoin d'espace réservé et ajoute simplement le STDIN à la fin des arguments.

Il suffit d'ajouter echo à vos exemples pour voir ce que fait xargs:

$ ls -1
Hello World/

Votre exemple utilise par erreur {}:

$ ls -1 | xargs echo file {}
file {} Hello World/

alors le file cmd voit des arguments de {} Hello World et des erreurs.

Si vous voulez utiliser explicitement {} dans votre appel xargs:

$ ls -1 | xargs -i echo file {}
file Hello World/

Ou sans espace réservé:

$ ls -1 | xargs echo file
file Hello World/

xargs comme appelé ci-dessus n'a pas besoin de {}. Il ajoute le STDIN à la fin de la commande sans espace réservé. L'utilisation de {} signifie généralement que vous voulez que le STDIN quelque part au milieu de la commande s'exécute, comme dans

$ ls -1 | xargs -i mv {} /path/to/someplace/.
johnnyB
la source
C'est très clair. Même si votre réponse est un peu tardive, sa lecture renforce ma compréhension.
foresightyj