Nota:
* Essa resposta provavelmente é mais profunda do que o caso de uso justifica e find 2>/dev/null
pode 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 find
chamadas 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 é bash
ouzsh
, existe uma solução robusta e razoavelmente simples , usando apenas find
recursos compatíveis com POSIX ; Embora bash
ela 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 grep
saí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 | cat
ao 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>
>(...)
bash
zsh
ksh
2> >(...)
ksh 93u+
grep -v 'Permission denied'
filtra para fora ( -v
) todas as linhas (do find
fluxo stderr de comando) que contenham a frase Permission denied
e 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 : find
o 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 find
a 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>&1
deve vir primeiro .
A captura de saída stdout em um arquivo antecipadamente permite 2>&1
enviar apenas mensagens de erro pelo pipeline, que grep
pode operar sem ambiguidade.
A única desvantagem é que o código de saída geral será do grep
comando , 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, find
o 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 find
có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
: 1
caso 0
contrá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 find
o 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 grep
via stdout.
Sem esses redirecionamentos, os dados (caminhos do arquivo) e as mensagens de erro seriam canalizados para o grep
stdout 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 denied
erros ainda podem surgir: find ! -readable -prune
relata esses erros para os itens filhos de diretórios para os quais o usuário atual tem r
permissão, mas não possui permissão x
(executável). O motivo é que, como o próprio diretório é legível, -prune
não é executado e a tentativa de descer para esse diretório aciona as mensagens de erro. Dito isto, o caso típico é a r
falta 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 find
comando, 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
-name
filtro, da seguinte forma:
find . ! -readable -prune -o -name '*.txt'
Isso, no entanto, não funciona conforme o esperado, porque a -print
açã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_folders
como 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_file
corre 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
:?