2012-03-01 2 views
3

Привет У меня есть своеобразная проблема, и я стараюсь, чтобы найти (каламбур) решение для него.Pipe Найти команду "stderr" команде

$> find ./subdirectory -type f 2>>error.log 

Я получаю сообщение об ошибке, что-то вроде «найти: ./subdirectory/noidea: Разрешение отказано» из этой команды, и это будет перенаправлен на error.log.

Есть ли способ, я могу конвейер STDERR в другую команду перед перенаправлением на error.log?

Я хочу быть в состоянии сделать что-то вроде

$> find ./subdirectory -type f 2 | sed "s#\(.*\)#${PWD}\1#" >> error.log 

, где я хочу, чтобы трубы только STDERR к СЭД команду и получить весь путь ошибки команды находят.

Я знаю, что трубопровод здесь не работает и, вероятно, не самый подходящий способ.

Моя проблема в том, мне нужно как стандартный вывод и STDERR и оба должны быть обработаны с помощью различных вещей одновременно.

EDIT: ОК. Небольшое изменение моей проблемы.

Теперь у меня есть скрипт, solve_problem.sh

В этом сценарии оболочки, у меня есть следующий код

ErrorFile="error.log" 
for directories in `find ./subdirectory -type f 2>> $ErrorFile` 
do 
    field1=`echo $directories | cut -d/-f2` 
    field2=`echo $directories | cut -d/-f3` 
done 

Та же проблема, но внутри сценария оболочки. Ошибка «find: ./subdirectory/noidea: Permission denied» должна перейти в $ ErrorFile и . Stdout должен быть присвоен переменной $ справочникам.

ответ

2

Pipe потоки вывода одновременно - идея взята из this post:

(find /boot | sed s'/^/STDOUT:/') 3>&1 1>&2 2>&3 | sed 's/^/STDERR:/' 

Пример вывода:

STDOUT:/boot/grub/usb_keyboard.mod 
STDERR:find: `/boot/lost+found': Brak dostępu 

Bash переназначения как 3>&1 1>&2 2>&3 свопов потоки вывода.

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

#!/bin/bash 
ErrorFile="error.log" 
(find ./subdirectory -type f 3>&1 1>&2 2>&3 | sed "s#^#${PWD}: #" >> $ErrorFile) 3>&1 1>&2 2>&3 | while read line; do 
    field1=$(echo "$line" | cut -d/-f2) 
    ... 
done 

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

Небольшой дополнительный комментарий - смотрите на странице -printf в справочной странице. Это может быть полезно для вас.

+0

Это полезный метод, но следует проявлять осторожность. В частности, у вас теперь есть сообщения об ошибках find, которые записываются в stdout с префиксом «STDERR:», а stdout поиска, идущего в stderr с префиксом «STDOUT:» Это потенциально запутывает. –

+0

@kupson: Очень удобное решение.Но я не уверен, что это сработает по моему сценарию. Я пробовал что-то вроде '(find ./subdirectory/ -type f) 3> & 2 2> & 1 1> & 3 | sed 's?^\ (find: \) \ (. * \)? \ 1 $ {PWD}/\ 2? " >> $ ErrorFile', но это не сработало для меня. Ошибки перенаправляются в файл журнала так, как я хочу, но _stdout_ не получает привязанный к переменной в цикле for (я обновил свою проблему) – latestVersion

+0

@latestVersion Я бы использовал цикл while в этой ситуации. – kupson

1

Если вам нужно перенаправить stderr на номер stdout, чтобы следующая команда в канале получала его как входной сигнал, вы можете использовать 2>&1.

Для получения дополнительной информации, пожалуйста, ознакомьтесь с практическим руководством all about redirection.

Edit: Даже если вам нужно отредактировать передать stdout далее в трубу, вы можете использовать sed для фильтрации сообщений об ошибках и записать их в файл:

$ find . -type f 2>&1 | sed '/^find:/{ 
> w error.log 
> d 
> }' 

В этом примере:

  • в find команде stderr перенаправляется stdout
  • в sed ошибках команды из find которые соответствуют регулярному выражению, записываются в файл (w error.log) и удаляются с вывода (d).
  • любая команда в конвейере по трубопроводу получит выход от find.

Примечание: Это будет работать как долгота, как и все сообщения об ошибках от find начала с find:. В противном случае регулярное выражение в sed должно быть изменено для правильного соответствия всем случаям.

+0

Трубопровод сам по себе не подходит n в моем случае, так как я хочу, чтобы ** stderr ** проходил через команду sed и ** stdout **, используя другой набор команд в моем скрипте. – latestVersion

+0

Я не совсем уверен, как это работает. Может быть, вы можете помочь мне понять, что здесь происходит. Также я мог бы заменить команду 'sed'? – latestVersion

+0

Я отредактировал объяснение, чтобы сделать его более ясным. Я надеюсь, что это помогает. – jcollado

0

Вы можете попробовать это (на баш), который, кажется, работает:

find ./subdirectory -type f 2> >(sed "s#\(.*\)#${PWD}\1#" >> error.log) 

Это делает следующее:

  1. 2> перенаправляет STDERR к
  2. >(...) подмена процесс (работает СЭД , который прилагается к ошибке.log)
+0

Это решение работает в командной строке. Но я столкнулся с синтаксической ошибкой, когда я попробовал ее в сценарии оболочки. В любом случае, вы можете помочь мне в этом? – latestVersion

+0

@latestVersion: Я просто попробовал линию, когда я разместил ее (в bash 4.2.20), и, похоже, она работает. обратите внимание, что _must_ будет пробелом после '2>' или вы получите синтаксическую ошибку. (на самом деле, должно быть пробел перед '> (...)', но в этом случае это то же самое.) – Hasturkun

Смежные вопросы