Отдельное состояние выполнения команд с каналами

В команде, где у нас есть много каналов, перенаправляющих их выходы дальше, есть ли способ узнать значение echo $? до половины его выполнения или до определенного количества труб, в отличие от общего состояния всей команды? Чтобы проиллюстрировать это, я запускаю команду ниже, чтобы получить временную метку файла, который будет преобразован в его эпоху,

 `ls -lrt --time-style=+"%b %d %Y %H:%M:%S" /some/path/*.dat|head -1|tr -s " "|cut -d " " -f 9|date --date - +%s` 

Но не получить то, что я хочу, когда я проверил вручную, разделив его на две половины,

 var1=`ls -lrt --time-style=+"%b %d %Y %H:%M:%S" /some/path/*.dat|head -1|tr -s " "|cut -d " " -f 9` var2=`date --date=$var1 +%s` 

В первой неповрежденной команде я все равно получаю вывод без какой-либо ошибки и не ожидаю этого, но я даже не хочу использовать две команды. Может ли кто-нибудь предложить в любом случае сделать это или где именно я заблуждаюсь?

Обновление: почему нижеследующие производят сегодняшнюю эпоху полуночи (что произойдет, если дана дата), чтобы получить более ранний вывод по каналам – хотя это не работает). Первый вопрос остается без ответа.

 -bash-3.2$ ls -lrt --time-style=+"%b %d %Y %H:%M:%S" *.dat|head -1|tr -s " "|cut -d " " -f9|date --date - +%s; date +%s 1429056000 #Midnight's 1429093077 #Current 

PS: Это была не настоящая эпоха.

В команде, где у нас есть много каналов, перенаправляющих их выходы дальше, есть ли способ узнать значение echo $? до половины его выполнения или до определенного количества труб, в отличие от общего состояния всей команды?

В bash есть переменная PIPESTATUS , которая представляет собой массив, содержащий статус выхода каждой команды в последнем конвейере.

 $ ls -lrt --time-style=+"%b %d %Y %H:%M:%S" /bin/*|head -1|tr -s " "| \ cut -d " " -f 9|date --date - +%s 1429070400 $ echo ${PIPESTATUS[@]} 141 0 0 141 0 $ kill -l `expr 141 - 128` PIPE 

Это говорит нам о том, что команды ls и cut вышли из SIGPIPE, что ожидается, потому что их вывод не был полностью поглощен следующей командой в конвейере.

В первой неповрежденной команде я все равно получаю вывод без какой-либо ошибки, и я не ожидаю этого.

Это потому, что команда date работает так, как она ожидает, но, я думаю, не так, как вы ожидаете.

date --date - не читает дату из stdin; вместо этого он использует - как строку даты. Я не вижу, где значение одиночного - задокументировано, но похоже, что оно равно 0 или 0000 , что означает «полночь текущего дня».

У вас есть эта команда

 ls -lrt --time-style=+"%b %d %Y %H:%M:%S" /some/path/*.dat|head -1|tr -s " "|cut -d " " -f 9|date --date - +%s 

Проблема в том, что date не ожидает его параметров через stdin , поэтому вам нужно разбить ее на две части. Вы уже сделали это во второй части своего Вопроса:

 var1=$(ls -lrt --time-style=+"%b %d %Y %H:%M:%S" /some/path/*.dat|head -1|tr -s " "|cut -d " " -f 9) echo "var1='$var1'" # eg var1='11:37:39' var2=$(date --date="$var1" +%s) echo "var2='$var2'" # eg var2='1429094259' 

Однако, когда вы запускаете команду date , она дает вам время (11:37:39 – 1429094259) на сегодня (сравните ее со значением для var2 с моим 11:04:45 – 1429092286, и вы увидите, что они очень аналогичный).

Может быть, stat --format '%Y' /tmp/path/*.dat будет проще?


Некоторые ответы на конкретные вопросы

Есть ли способ узнать значение echo $? [в середине трубы]? Не прямо, нет. Однако вы можете разделить конвейер на две части с временным файлом для хранения промежуточных результатов или сэкономить $? как вы идете.

 cmd1 | ( cmd2; SS=$?; echo $SS >/tmp/cmd2.ss; exit $SS ) | cmd3 cmd2_status=$(</tmp/cmd2.ss) 

Как я могу сделать то, что хочу в одном конвейере? Вы можете оценить время и передать это на сегодняшний день, что-то вроде этого

 date --date=$( cmd1 | cmd2 | cmd2 ) +%s 

Почему date --date=- время в полночь? Команда date пытается сделать что-то значимое с недопустимой датой «-». Бывает, что это заканчивается тем, что интерпретируется как «полночь сегодня». Впрочем, я бы не стал рисковать; если вы действительно хотите полночь, я бы пошел на ясную date --date='00:00'