bash xargs: одна и та же команда дает другой вывод

527
stas

Когда я бегу

ls -1 *.a | xargs -I{} echo {} | sed 's/.a//' 

Выход

1 2 3 

Когда я бегу

ls -1 *.a | xargs -I{} bash -c "echo {} $(echo {} | sed 's/.a//')" 

и вывод

1.a 1.a 2.a 2.a 3.a 3.a 

В чем причина этой аномалии?

1
Я полагаю, что оболочка выполняется до `$ (echo {} | sed 's / .a //')`, которая отвечает `{}`. Затем у вас есть `bash -c" echo {} {} "`, на который действует `xargs -I {}`, заменяющий `{}` вывод `ls * .a`. Ps> Вам не нужно `-1`, когда вы передаете` ls`, _somehow, он_ знает, что это канал, и это автоматически. Hastur 8 лет назад 1
Хастур прав. Запустите `bash -xc 'ls * .a | xargs -I {} bash -c "echo {} $ (echo {} | sed s / .a //)" '`, и вы увидите. guest-vm 8 лет назад 1
@ Guest Thx, я писал то же самое ... :-), но со слишком большим количеством слов. Hastur 8 лет назад 0

1 ответ на вопрос

1
Hastur

Давайте предположим, что ваш в каталоге наличие файлов 1.a, 2.a, 3.a.

С помощью команды

ls *.a | xargs -I{} echo {} | sed 's/.a//' 

у вас нет подоболочек, вывод lsкоторых передается по каналу, xargsкоторые делают его замены. Затем вывод передается по каналу sed. Отсюда ваш первый результат.

С помощью команды

ls *.a | xargs -I{} bash -c "echo {} $(echo {} | sed 's/.a//')" 

у вас есть новый элемент $(echo {} | sed 's/.a//').

Расширяется и становится

echo {} # -- > {} echo {} | sed 's/.a//' # -- > {} again the same. 

так что ваша команда может быть переписана как

 ls *.a | xargs -I{} bash -c "echo {} {} " 

это дает ваш второй вывод.

Как только что сказал и гость в своем комментарии, отладьте ваш скрипт [ 1 ] (или команду); с set -xвами включить отладку в текущей оболочке или сценарии и с set +xотключить его:

set -x  ls *.a | xargs -I{} bash -c "echo {} $(echo {} | sed 's/.a//')" set +x  

и вы увидите каждый шаг

+ ls --color=auto 1.a 2.a 3.a ++ echo '{}' ++ sed s/.a// + xargs '-I{}' bash -c 'echo {} {}' 1.a 1.a 2.a 2.a 3.a 3.a 
Есть ли обходной путь? stas 8 лет назад 0
Какой выход вы хотите получить? Какова была ваша идея? Hastur 8 лет назад 0
несоответствие трассировки отладки> _ < guest-vm 8 лет назад 0
@stas `ls * .a | xargs -I {} bash -c "echo {} \ $ (echo {} | sed 's / .a //')" ` guest-vm 8 лет назад 0
@guest `> _ <` Спасибо, я скопировал из другой команды ... Меня отвлек _querelle_ на другой [вопрос] (http://superuser.com/q/1093111/257269) ... Hastur 8 лет назад 0