Чтение из stderr в c

Вы бы хотели использовать только:

 find. -name '*.txt'  -exec cmd {} \;

форма для тех cmds, которые могут принимать только один аргумент. Это не относится к grep. Сgrep:

 find. -name '*.txt'  -exec grep foo /dev/null {} +

(или используйте -Hс GNUgrep). Подробнее об этом в Recursive grep vs find / -type f -exec grep {} \; Что эффективнее/быстрее?

Теперь для замены, то же самое, perl -piможет принимать более одного аргумента:

 find. -name '*.txt' -type f -exec perl -pi -e s/foo/bar/g {} +

Теперь это будет перезаписывать файлы независимо от того, содержат они fooили нет. Вместо этого вы можете захотеть (предполагать GNU grepи xargsили совместимые):

 find. -name '*.txt' -type f -exec grep -l --null foo {} + |
   xargs -r0 perl -pi -e s/foo/bar/g

или:

 grep -lr --null --include='*.txt' foo. |
   xargs -r0 perl -pi -e s/foo/bar/g

Таким образом, перезаписываются только те файлы, которые содержат foo.


Кстати,--include=*.txt(--includeявляется еще одним расширением GNU. )представляет собой шелл-шаблон, поэтому его следует указать в кавычках. Например, если в текущем каталоге есть файл с именем --include=foo.txt, оболочка расширит --include=*.txtдо него перед вызовом grep. А если нет, то во многих оболочках вы получите ошибку о том, что glob не соответствует ни одному файлу.

Так и хочетсяgrep --include='*.txt'

1
21.03.2020, 17:57
4 ответа

stderrпредназначен для письма, а не для чтения. Иногда это dupликата stdin(, например. когда все 3 входа/выхода/ошибки подключены к клемме ). Чтобы прочитать stderr другой программы, вы перенаправляете stderr этой программы на stdin другой.

напр. to направляет stdoutв файл, а stderr— в ./myprogramsstdin.

command 2>&1 >a_file |./myprogram
1
28.04.2021, 23:19

Чтобы оболочка установила перенаправление ввода для stderr, вы должны использовать <, <<или <<<и префикс номера дескриптора файла:

./myprog 2< somefile.txt

или

./myprog 2<<< "some text"

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

Возможно, вы захотите еще раз подумать, есть ли какой-то другой способ делать то, что вы делаете. По крайней мере, рассмотрите возможность использования, например. fd 3, если идея состоит в том, чтобы предоставить какой-либо ввод в программу.

-1
28.04.2021, 23:19

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

(Примечание :В этом ответе я использую фактические номера файловых дескрипторов. C-потоки , такие как stderr, на самом деле не должны соответствовать этим файловым дескрипторам, поскольку программа может изменить их, и это добавляет путаницы в разговоры о том, что делают C-потоки. Ваша программа использует read().)

Файловый дескриптор 2 открыт для чтения и записи

Для программ в сеансах входа в систему, где в родительском процессе не использовалось перенаправление, стандартная ошибка файлового дескриптора 2 ()обычно является дубликатом файлового дескриптора 0 (стандартного ввода ). Оба они ссылаются на одно и то же базовое описание файла , которое обычно является терминалом сеанса входа в систему (, открытым и дублированным ttymonили, в более старых системах, gettyв самом начале сеанса. ).

Если вы читаете из файлового дескриптора 2, вы получаете тот же ввод, как если бы вы читали из файлового дескриптора 0.

BTW :Чтение файлового дескриптора 2 часто выполнялось для таких вещей, как ввод пароля; до того, как было представлено устройство /dev/tty, примерно в 1977 году. Причина чтения из файлового дескриптора 2 заключалась в том, чтобы получить ввод с исходного терминала, когда файловый дескриптор 0 был перенаправлен в другое место (, как в случае в середине конвейера, например ).

Несмотря на то, что /dev/ttyдоступен уже давно, более 40 лет, POSIX по-прежнему требует, чтобы файловый дескриптор 2 также был открыт для чтения.

Чего не делает ваша программа

Чтение выходных данных файлового дескриптора 2 другой программы — это другое дело. Вы не можете легко сделать это само по себе , не объединяя стандартный вывод со стандартной ошибкой. Обычно это включает серию 3>&1 1>&2 2>&3или подобных свопов. Несколько оболочек разрешают конвейеры для дескриптора выходного файла 2, вызывая

prog1 2| prog2

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

Отправка ввода в вашу программу

Если вы хотите, чтобы ваша программа, читающая из файлового дескриптора 2, читала из чего-то отличного от терминала, вы, конечно, перенаправляете этот файловый дескриптор. Вы могли бы использовать обычный ввод синтаксис перенаправления (оператор <в оболочке ), но библиотеки в вашей программе или даже другой код, который вы написали в другом месте, будут иметь предположения, что они могут писать в этот файловый дескриптор.

Оболочка позволяет использовать оператор перенаправления <>, который явно открывает файл как для чтения, так и для записи. Это то, что вы используете при перенаправлении файлового дескриптора вашей программы 2.

./myprogram 2<>filename

Помимо перенаправления оболочки, существует множество инструментов, позволяющих манипулировать файловыми дескрипторами. Например, :С цепочкой Лорана Берко -, загружающейredirfdинструмент, который поставляется с execline,это перенаправление больше похоже на вашу гипотезу:

redirfd -u 2 filename./myprogram

Существует также синтаксис оболочки в оболочках Bourne Again и Z (, но не в оболочках Almquist )для предоставления «здесь документы» и «здесь строки» для файлового дескриптора 2. Обратите внимание, что файловый дескриптор 2 в этом случае открывается только для чтения этими оболочками.

./myprogram 2<<< "here string"
0
28.04.2021, 23:19

С такими оболочками, как bashи zsh(, но не с простым POSIX sh), вы можете перенаправить стандартную ошибку одной программы на стандартный ввод другой программы через firstprogram 2> >(second program).

Пример:

$ perl -E 'say "perl stdout"; warn "perl stderr\n"' 2> >(awk '{print "awk", $0}')
perl stdout
awk perl stderr
0
28.04.2021, 23:19

Теги

Похожие вопросы