xargs -I replace-str Опция различия

16

Насколько я понимаю, следующее должно означать то же самое:

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

если опция -I не указана, по умолчанию используется -I {}.

Я хочу перечислить все файлы в текущем каталоге и выполнить fileкоманду для каждого из них. У некоторых есть пробелы в их именах. Однако я заметил разницу. См. ниже:

$ 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

Если явно указано -I {}, пропуски в именах файлов обрабатываются как и ожидалось.

foresightyj
источник
3
«если опция -I не указана, по умолчанию используется -I {}» - это неверно, по крайней мере для GNU xargs.
jjlin
Я понимаю свою ошибку. Я должен указать либо xargs fileили xargs -I{} file {}. Не должно быть xargs file {}. Я предполагаю, что при явном указании -I {} bash будет воспринимать это как file "Hello World". Без -I {} это рассматривается как file Hello World.
foresightyj
1
(1) Это обсуждение имеет мало общего с оболочкой (bash). (2) Хорошо, что вы знаете эту -1опцию ls, но она включена по умолчанию, когда выводом lsявляется файл или канал, поэтому вам здесь это не нужно. (3) Вы путаете -Iс устаревшей опцией -i(в нижнем регистре I). -ifooэквивалентно -Ifoo, но обычный -iэквивалентно -I{}. Но используйте -I{}. (4) Если вы действительно хотите делать то, что говорите, то почему бы просто не сказать file *?
Скотт
@ Scott Моим первоначальным намерением было написать `найти. имя "* .mov" | xargs -I {} file {} `для рекурсивного поиска всех файлов mov и запуска fileих. Но я придумал более простой пример использования ls. Вы правы. За это file *самое лучшее.
foresightyj
1
найти есть -exec.
Кристиан Чиупиту

Ответы:

20

-IТребует определенного заполнителя. -iВариант будет предполагать , {}является заполнителем. Именно здесь я нашел предположение {}, man xargsпо крайней мере, в Cygwin и CentOS.

Вызванный xargs без какой-либо опции не нуждается в заполнителе, и он просто добавляет STDIN в конец аргументов.

Просто добавьте echoк своим примерам, чтобы увидеть, что делает xargs:

$ ls -1
Hello World/

Ваш пример по ошибке использует {}:

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

поэтому filecmd видит аргументы {} Hello Worldи ошибки.

Если вы хотите явно использовать {}в вашем вызове xargs:

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

Или без заполнителя:

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

Xargs, как указано выше, не нуждается в {}. Он добавляет STDIN в конец команды без заполнителя. Использование {} обычно означает, что вы хотите, чтобы STDIN где-то в середине cmd выполнялся, как в:

$ ls -1 | xargs -i mv {} /path/to/someplace/.
johnnyB
источник
Это очень ясно. Хотя ваш ответ немного запоздал, но чтение его действительно укрепляет мое понимание.
foresightyj