paste -d",''," ./file1 - ./file2 - - </dev/null >out
... учитывая данные вашего примера, которые записываются в вывод:
'1','1','1,2',
'2','2','1,3',
'3','3','1,4',
'4','4','1,5',
'5','5','1,6',
'6','6','1,7',
'7','7','1,8',
'8','8','1,9',
'9','9','1,10',
'10','10','2,1',
,'2,3',
,'2,4',
,'2,5',
,'2,6',
,'2,7',
,'2,8',
,'2,9',
,'',
Мне немного сложно точно сказать, каковы критерии для остановки вывода, но записать вывод, идентичный выводу вашего примера:
{ paste -d",''," ./file1 - ./file2 - - |
sed -ne's/,/&/4p;t' -eq
} </dev/null
'1','1','1,2',
'2','2','1,3',
'3','3','1,4',
'4','4','1,5',
'5','5','1,6',
'6','6','1,7',
'7','7','1,8',
'8','8','1,9',
'9','9','1,10',
'10','10','2,1',
Вы можете использовать именованный канал и соединить два процесса вручную. Запускайте их в обратном порядке, чтобы левая сторона -работала на переднем плане, и вы получали статус выхода из $?
, как обычно.
#!/bin/sh
dir=$(mktemp -d)
mkfifo "$dir/p"
cat < "$dir/p" > /dev/null &
( echo foo; exit 12; ) > "$dir/p"
echo "exit status: left: $?"
rm -r "$dir"
Или, если вы хотите и то, и другое, получите PID фонового процесса из $!
и wait
, чтобы получить статус выхода.
#!/bin/sh
dir=$(mktemp -d)
mkfifo "$dir/p"
( echo foo; exit 12; ) > "$dir/p" & # left-hand side
pidleft=$!
( cat; exit 34; ) < "$dir/p" > /dev/null & # right-hand side
pidright=$!
wait "$pidleft"; exitleft=$?
wait "$pidright"; exitright=$?
echo "exit status: left: $exitleft right: $exitright"
rm -r "$dir"
Можно еще оставить вторую часть трубы на переднем плане, я просто хотел сделать это симметрично.
Вы также можете, например,. сохранить статус выхода в файлы и получить их оттуда:
#/bin/sh
( somecmd; echo "$?" > exit1 ) | ( cat; echo "$?" > exit2)
echo "exit status: left: $(cat exit1) right: $(cat exit2)"
Я не думаю, что именованный канал будет здесь полезен, поскольку статус выхода занимает всего пару байтов. Оболочка будет ждать завершения конвейера, прежде чем пытаться прочитать exit1
и exit2
во второй строке.
Если вместо этого вы хотите использовать именованные каналы, вам необходимо перевести конвейер в фоновый режим, поскольку запись в каналы блокируется до тех пор, пока не будет открыта сторона чтения.
#/bin/sh
mkfifo exit1 exit2
( somecmd; echo "$?" > exit1 ) | ( cat; echo "$?" > exit2) &
echo "exit status: left: $(cat exit1) right: $(cat exit2)"
Однако, если cat
s читает каналы по какой-то причине, подоболочки, пишущие в них, будут блокироваться на неопределенный срок в фоновом режиме.
Вы можете отключить свой скрипт, закрыв стандартный вывод в левой части конвейера и стандартный ввод справа сразу после выхода из фактических команд:
Пример:
#! /bin/dash
rm -f /tmp/s1 /tmp/s2
mkfifo /tmp/s1 /tmp/s2
{ (echo yes; exit 13); s1=$?; exec >&-; echo $s1 >/tmp/s1 & } | { (cat; exit 17); s2=$?; exec <&-; echo $s2 >/tmp/s2 & }
echo "`cat /tmp/s1` `cat /tmp/s2`"
Замените (...; exit..)
соответствующими командами.
Закрытие стандартного входа в правой части канала после выхода фактической команды вызывает запись ()в левой части для получения SIGPIPE или EPIPE вместо блокировки при попытке передать команду echo... >fifo &
из правый (, который сам заблокирован в открытом ()), и закрытие стандартного вывода слева вызывает чтение ()в правой части канала для получения EOF вместо попытки передать канал из блокирующего echo... >fifo &
слева.
Спасибо @ilkkachu за исправление.