Unix: запустить 2 команды, которые получают ввод из канала? - PullRequest
5 голосов
/ 15 августа 2010

Обновлено: Спасибо за ваши ответы. Как я уже сказал, моя буква q была просто переводом моего варианта использования. Позвольте мне подробнее узнать о том, чего я хочу достичь. В моем dev env мы используем "ade" в качестве нашей системы контроля версий, что я хочу сделать:

ade describetrans | awk '/myapps/{ print $2 }' | sort -fr | xargs -iF ade unbranch F 

Теперь, каждый раз, когда я запускаю команду unbranch, создается новый файл / dir. поэтому мне нужно запустить ade checkin -all после всех моих команд ветвления. Поэтому мне нужно что-то вроде

"pre part till sort" | xargs -iF (ade unbranch + ade checkin -all) 

Есть ли способ запустить 2 команды на операторе канала?

Спасибо

Оригинальный вопрос:

Я могу перевести имеющийся у меня вариант использования в следующий:

Мне нужно получить 1-ю строку файла. Я делаю

cat file | head -1 

Теперь я хочу сделать это в списке файлов. Как мне сделать следующее в одной команде Unix ?? Например:

find . -name "*.log" | ( xargs -iF cat F  | head -1 )

Очевидно, что скобки в приведенной выше команде не работают.

есть ли способ передать вывод команды find и выполнить с ней 2 команды (cat и head)? Пробовал с помощью; и &&, но не помогите. Я могу создать скрипт - но хотел сделать это одной командой.

Опять же - это просто перевод дела, которое у меня есть.

спасибо Рохан

Ответы [ 5 ]

4 голосов
/ 15 августа 2010

Прежде всего, head принимает более одного имени файла, поэтому вы можете просто написать:

 head -q -n 1 *.log

или:

find . -name '*.log' -exec head -n 1 '{}' ';'

Однако, если вы действительно нужно продублировать поток, затем использовать tee и сделать что-то вроде:

 wget -O - http://example.com/dvd.iso | tee >(sha1sum > dvd.sha1) > dvd.iso

Этот пример взят из info coreutils 'tee invocation'.


ОБНОВЛЕНИЕ (после комментария ade) В вашем случае tee не будет работать.Вам нужно выполнить задачу после завершения другой задачи, и tee будет запускать задачи более или менее одновременно (буферизация по модулю).

Другой подход будет работать, , при условии, что встроки ввода (серьезная проблема, я знаю, но я не знаю, как ее преодолеть прямо сейчас).Я начну с общего решения:

echo -e 'Foo\nBar\nBaz' | ( for i in `cat` ; do echo 1$i ; echo 2$i ; done )

Здесь echo -e 'Foo\nBar\nBaz' создает пример многострочного ввода, echo 1$i - первая команда для запуска, echo 2$i - вторая команда для запуска.

Я не знаком с ade, и у меня его не установлено в моей системе, но я предполагаю, что в вашем случае что-то подобное может работать:

ade describetrans | awk '/myapps/{ print $2 }' | sort -fr | ( for i in `cat` ; do ade unbranch $i ; ade checkin -all $i ; done )
1 голос
/ 15 августа 2010

Бесполезное использование cat.Просто передайте имена файлов в head:

find . -name '*.log' -exec head -n 1 '{}' '+'

или

find . -name '*.log' -print0 | xargs -0 head -n 1

РЕДАКТИРОВАТЬ: Это напечатает заголовки для каждого файла.В Linux это можно подавить с помощью -q, но в других системах вы должны убедиться, что head вызывается с одним аргументом:

find . -name '*.log' -exec head -n 1 '{}' ';'
0 голосов
/ 25 августа 2010

Я не знаю ade, поэтому мне придется угадать, что на самом деле хотят выполнить 2 команды.Но если у вас установлен GNU Parallel http://www.gnu.org/software/parallel/, один из них должен работать:

ade describetrans | awk '/myapps/{ print $2 }' | sort -fr |
parallel -j1 ade unbranch {} ";" ade checkin -all {}

ade describetrans | awk '/myapps/{ print $2 }' | sort -fr |
parallel -j1 ade unbranch {} ";" ade checkin -all

ade describetrans | awk '/myapps/{ print $2 }' | sort -fr |
parallel -j1 ade unbranch {} ; ade checkin -all

Если ade может работать параллельно, вы можете удалить -j1.

Посмотрите вступительное видео для GNU Parallel, чтобы узнать больше: http://www.youtube.com/watch?v=OpaiGYxkSuQ

0 голосов
/ 15 августа 2010

Попробуйте

ade describetrans | awk '/myapps/{ print $2 }' | sort -fr | xargs sh -c 'ade unbranch "$@"; ade checkin -all "$@"' arg0

Это предполагает, что ade принимает несколько файлов одновременно и ade checkin -all необходимо вызывать для каждого файла.

Строка arg0 предоставляетзначение $0 в строке -c.

0 голосов
/ 15 августа 2010

Вы делаете это намного сложнее, чем нужно, путем ввода ввода в head вместо простого присвоения ему имени файла:

head -n1 `find -X . -name '*.log' | xargs`

Если вам не нужноЧтобы просмотреть подкаталоги, вы можете сделать его еще проще:

head -n1 *.log

Вы можете отсеивать заголовки имен файлов, отправляя команду grep: | grep -v '^(==> .* <==)?$' | grep -v '^$'

...