Использование grep с pipe и ampersand для фильтрации ошибок от find

22

Я использую Cygwin, чтобы найти файл на Cygdrive.

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

find -name 'myfile.*' |& grep -v "Permission denied"

Я не понимаю, почему амперсанд должен быть введен в эту команду, ожидал, что это сработает, но это не так.

find -name 'myfile.*' | grep -v "Permission denied"

Пожалуйста, объясните значение амперсанда.

Хенрик К
источник

Ответы:

24

В Unix-подобных системах есть два пути вывода, которые, если оставить их без изменений, отправят вывод на ваш экран. Стандартная ошибка (или stderr) - это та, которая фиксирует большинство сбоев и состояний ошибок.

Чтобы передать сообщение об отказе в разрешении в stderr тому же потоку вывода, что и «обычный вывод», необходимо объединить их. В вашем примере для grep -vправильной работы с ним вы комбинируете stdout (стандартный вывод) и stderr с загадочным синтаксисом, который вы видите.

Из руководства по GNU Bash, раздел 3.2.2 Трубопроводы :

Если используется ' |&', стандартная ошибка command1 , в дополнение к стандартному выводу, подключается к стандартному вводу command2 через канал; это сокращение для 2>&1 |. Это неявное перенаправление стандартной ошибки на стандартный вывод выполняется после любых перенаправлений, указанных в команде.

Кроме того, как указывает гейра, если вы хотите просто избавиться от вывода stderr, вы бы хотели сделать что-то вроде

find -name 'myfile.*' 2> /dev/null

или возможно

find -name 'myfile.*' 2> /tmp/errorlog

И обратите внимание, что если у вас есть строки команд, например, для findпередачи их выходных данных, xargsвам потребуется поместить весь конвейер команд в круглые скобки, чтобы захватить выходные данные всех компонентов команды. Например,

(find | egrep ^[RS].[0-9]+/.svg] | xargs head -1 )  2> /dev/null

Если вы пропустили скобки и сделали это вместо этого -

find | egrep ^[RS].[0-9]+/.svg] | xargs head -1 2> /dev/null

вы все равно увидите ошибки отклоненного разрешения в find или egrep, но stderr будет перенаправлен на xargs.

Как вы уже видели, вы, вероятно, выбросили бы stderr только после просмотра его содержимого во время тестового прогона.

Обратите внимание, что с GNU findи, насколько я могу судить, любым POSIX-совместимым find, этот -printпараметр является неявным. Вы все еще можете предоставить это явно, если хотите.

belacqua
источник
Похоже, только bash4 + wiki.bash-hackers.org/bash4#redirection
Люк Экстон
1
@ LukeExton Да. В других оболочках 2>&1 |может использоваться вместо |&(т. Е. Можно явно перенаправить stderr в stdout, а затем передать это следующей команде в конвейере).
Элия ​​Каган
2> >( grep filter )также удобно
user1133275
1

Если вы хотите игнорировать сообщения об ошибках, просто перенаправьте stderr в / dev / null.

find . -name 'myfile.*' -print 2>/dev/null

Также рассмотрите возможность чтения http://mywiki.wooledge.org/UsingFind .

geirha
источник