Nota:
* Essa resposta provavelmente é mais profunda do que o caso de uso justifica e find 2>/dev/nullpode ser boa o suficiente em muitas situações. Pode ainda ser interessante para uma perspectiva de plataforma cruzada e para a discussão de algumas técnicas avançadas de shell, com o objetivo de encontrar uma solução o mais robusta possível, mesmo que os casos evitados possam ser amplamente hipotéticos.
* Se o seu sistema estiver configurado para mostrar mensagens de erro localizadas , prefixe as findchamadas abaixo com LC_ALL=C( LC_ALL=C find ...) para garantir que as mensagens em inglês sejam relatadas, para que grep -v 'Permission denied'funcione conforme o esperado. Invariavelmente, no entanto, quaisquer mensagens de erro que não são exibidas estará então em Inglês também.
Se seu shell é bashouzsh , existe uma solução robusta e razoavelmente simples , usando apenas findrecursos compatíveis com POSIX ; Embora bashela própria não faça parte do POSIX, a maioria das plataformas Unix modernas vem com ela, tornando esta solução amplamente portátil:
find . > files_and_folders 2> >(grep -v 'Permission denied' >&2)
Nota: Há uma pequena chance de que parte da grepsaída possa chegar após a find conclusão, porque o comando geral não espera o comando interno >(...)terminar. Em bash, você pode impedir isso anexando | catao comando.
>(...)é uma substituição do processo de saída (raramente usada) que permite redirecionar a saída (neste caso, stderr output ( ) para o stdin do comando interno .
Além de e , também os suporta, em princípio , mas tentando combiná-los com o redirecionamento de stderr , como é feito aqui ( ), parece ser silenciosamente ignorado (em ).2>>(...)
bashzshksh2> >(...)ksh 93u+
grep -v 'Permission denied'filtra para fora ( -v) todas as linhas (do findfluxo stderr de comando) que contenham a frase Permission deniede saídas das linhas restantes para stderr ( >&2).
Esta abordagem é:
robusto : grepé aplicado apenas a mensagens de erro (e não a uma combinação de caminhos de arquivos e mensagens de erro, potencialmente levando a falsos positivos) e mensagens de erro que não sejam negadas pela permissão são passadas para o stderr.
efeito colateral free : findo código de saída é preservado: a incapacidade de acessar pelo menos um dos itens do sistema de arquivos encontrados resulta em código de saída 1(embora isso não indique se ocorreram outros erros além dos negados pela permissão).
Soluções compatíveis com POSIX:
As soluções totalmente compatíveis com POSIX têm limitações ou exigem trabalho adicional.
Se finda saída deve ser capturada em um arquivo de qualquer maneira (ou suprimida por completo), a solução baseada em pipeline da resposta de Jonathan Leffler é simples, robusta e compatível com POSIX:
find . 2>&1 >files_and_folders | grep -v 'Permission denied' >&2
Observe que a ordem dos redirecionamentos é importante: 2>&1deve vir primeiro .
A captura de saída stdout em um arquivo antecipadamente permite 2>&1enviar apenas mensagens de erro pelo pipeline, que greppode operar sem ambiguidade.
A única desvantagem é que o código de saída geral será do grepcomando , não do comandofind , o que significa: se não houver nenhum erro ou apenas erros de permissão negada, o código de saída será 1( falha de sinalização ), caso contrário ( erros diferentes dos negados pela permissão) 0- que é o oposto da intenção.
Dito isso, findo código de saída raramente é usado de qualquer maneira , pois muitas vezes transmite pouca informação além de falhas fundamentais , como a passagem de um caminho inexistente.
No entanto, o caso específico de apenas algunsdos caminhos de entrada inacessíveis devido à falta de permissões, é refletido no findcódigo de saída (no GNU e no BSD find): se ocorrer um erro de permissão negada para qualquer um dos arquivos processados, o código de saída será definido como 1.
A seguinte variação aborda isso:
find . 2>&1 >files_and_folders | { grep -v 'Permission denied' >&2; [ $? -eq 1 ]; }
Agora, o código de saída indica se ocorreu algum erro diferente Permission denied : 1caso 0contrário , caso contrário.
Em outras palavras: o código de saída agora reflete a verdadeira intenção do comando: success ( 0) é relatado, se nenhum erro ou apenas erros com permissão negada ocorrerem.
Isso é sem dúvida ainda melhor do que apenas passar findo código de saída, como na solução na parte superior.
gniourf_gniourf nos comentários propõe uma generalização (ainda compatível com POSIX) desta solução usando redirecionamentos sofisticados , que funcionam mesmo com o comportamento padrão de imprimir os caminhos de arquivo no stdout :
{ find . 3>&2 2>&1 1>&3 | grep -v 'Permission denied' >&3; } 3>&2 2>&1
Em resumo: o descritor de arquivo personalizado 3é usado para trocar temporariamente stdout ( 1) e stderr ( 2), para que somente as mensagens de erro possam ser canalizadas grepvia stdout.
Sem esses redirecionamentos, os dados (caminhos do arquivo) e as mensagens de erro seriam canalizados para o grepstdout e grep, portanto, não seriam capazes de distinguir entre a mensagem de erro Permission denied e um arquivo (hipotético) cujo nome contém a frase Permission denied.
Como na primeira solução, no entanto, o código de saída relatado será grep, e não find, mas a mesma correção acima pode ser aplicada.
Notas sobre as respostas existentes:
Há vários pontos a serem observados sobre a resposta de Michael Brux , find . ! -readable -prune -o -print:
Requer GNU find ; notavelmente, não funcionará no macOS. Obviamente, se você precisar apenas do comando para trabalhar com o GNU find, isso não será um problema para você.
Alguns Permission deniederros ainda podem surgir: find ! -readable -prunerelata esses erros para os itens filhos de diretórios para os quais o usuário atual tem rpermissão, mas não possui permissão x(executável). O motivo é que, como o próprio diretório é legível, -prunenão é executado e a tentativa de descer para esse diretório aciona as mensagens de erro. Dito isto, o caso típico é a rfalta de permissão.
Nota: O ponto a seguir é uma questão de filosofia e / ou caso de uso específico, e você pode decidir que não é relevante para você e que o comando se adapta bem às suas necessidades, especialmente se simplesmente imprimir os caminhos for o que você faz:
- Se você conceituar a filtragem das mensagens de erro negadas por permissão como uma tarefa separada que deseja aplicar a qualquer
find comando, a abordagem oposta de impedir proativamente os erros negados por permissão requer a introdução de "ruído" no findcomando, que também introduz complexidade e armadilhas lógicas .
- Por exemplo, o comentário mais votado na resposta de Michael (até o momento em que este artigo foi escrito) tenta mostrar como estender o comando incluindo um
-namefiltro, da seguinte forma:
find . ! -readable -prune -o -name '*.txt'
Isso, no entanto, não funciona conforme o esperado, porque a -printação à direita é necessária (uma explicação pode ser encontrada nesta resposta ). Essas sutilezas podem introduzir bugs.
A primeira solução na resposta de Jonathan Leffler , find . 2>/dev/null > files_and_folderscomo ele mesmo afirma, cegamente silencia todas as mensagens de erro (e a solução é complicada e não totalmente robusto, como ele também explica). Pragmaticamente falando , no entanto, é a solução mais simples , pois você pode se contentar em supor que todo e qualquer erro esteja relacionado à permissão.
A resposta de névoa , sudo find . > files_and_folders, é conciso e pragmático, mas mal aconselhado para qualquer outra coisa do que simplesmente imprimir nomes de arquivos , por razões de segurança: porque você está executando como a raiz do usuário, "o risco de ter todo o seu sistema a ser confuso por um erro no achado ou uma versão mal-intencionada ou uma invocação incorreta que escreve algo inesperadamente, o que não poderia acontecer se você executasse isso com privilégios normais "(de um comentário sobre a resposta da névoa por triplicado ).
A 2ª solução na resposta de viraptor , find . 2>&1 | grep -v 'Permission denied' > some_filecorre o risco de falsos positivos (devido ao envio de uma mistura de stdout e stderr através do gasoduto), e, potencialmente, ao invés de relatar não erros negou--permission via stderr, captura-los ao lado dos caminhos de saída no arquivo de saída.
find . 2>&1 > files_and_folders | grep -v 'Permission denied' >&2:?