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
:?{ find . 3>&2 2>&1 1>&3 | grep -v 'Permission denied' >&3; } 3>&2 2>&1
>(...)
são específicas do Bash.find
seja enfatizada e anunciada:find
o código de saída é notoriamente inútil. Aqui, é muito provável que seja diferente de zero (e inútil).execute/search
permissão no modo de arquivo para 'pesquisar' um diretório (recuperar os inodes dos arquivos contidos).find
faz isso para descer para um subdiretório (além de exigirread
permissão para listar os arquivos em um diretório). Este não é um 'bug' ou 'erro de portabilidade'.Usar:
Isso oculta não apenas os
Permission denied
erros, é claro, mas todas as mensagens de erro.Se você realmente deseja manter outros erros possíveis, como muitos saltos em um link simbólico, mas não a permissão negada, provavelmente precisará adivinhar que não possui muitos arquivos chamados 'permissão negada' e tentar:
Se você deseja estritamente filtrar apenas o erro padrão, pode usar a construção mais elaborada:
O I / O redirecionamento no
find
comando é:2>&1 > files_and_folders |
. O canal redireciona a saída padrão para ogrep
comando e é aplicado primeiro. O2>&1
erro padrão é enviado para o mesmo local da saída padrão (o tubo). O> files_and_folders
envia saída padrão (mas não o erro padrão) para um arquivo. O resultado líquido é que as mensagens gravadas com erro padrão são enviadas pelo canal e a saída regular defind
é gravada no arquivo. Osgrep
filtros filtram a saída padrão (você pode decidir o quão seletiva você deseja que seja e pode ter que alterar a ortografia dependendo do código de idioma e do sistema operacional) e o final>&2
significa que as mensagens de erro sobreviventes (gravadas na saída padrão) voltam ao erro padrão mais uma vez. O redirecionamento final pode ser considerado opcional no terminal, mas seria uma boa idéia usá-lo em um script para que as mensagens de erro apareçam no erro padrão.Existem inúmeras variações sobre esse tema, dependendo do que você deseja fazer. Isso funcionará em qualquer variante do Unix com qualquer derivado de shell Bourne (Bash, Korn, ...) e qualquer versão do POSIX compatível com
find
.Se você deseja se adaptar à versão específica de
find
seu sistema, pode haver opções alternativas disponíveis. O GNU,find
em particular, possui inúmeras opções não disponíveis em outras versões - veja a resposta atualmente aceita para um desses conjuntos de opções.fonte
2>/dev/null
, sem espaço!2>
é uma única unidade sem espaços; você pode ter um espaço entre ele e o nome do arquivo. Da mesma forma com outros redirecionamentos, como2>&1
(que redireciona o erro padrão para o mesmo local da saída padrão) ou2>&-
fecha o erro padrão, etc. Consulte Redirecionamentos para obter os detalhes sangrentos restantes. (O código acima é genérico POSIX-como o escudo, não é específico parabash
.)Usar:
ou mais geralmente
Trabalha com: find (GNU findutils) 4.4.2. Fundo:
-readable
teste corresponde aos arquivos legíveis. O!
operador retorna verdadeiro, quando teste é falso. E! -readable
corresponde a diretórios não legíveis (& arquivos).-prune
ação não desce no diretório! -readable -prune
pode ser traduzido para: se o diretório não estiver legível, não desça nele.-readable
teste leva em consideração as listas de controle de acesso e outros artefatos de permissões que o-perm
teste ignora.Veja também
find
(1) a página de manual para muitos mais detalhes.fonte
-o
:find . ! -readable -prune -o -name '*.txt'
find
não inclui-readable
como opção; nem ofind
BSD e, portanto, o Mac OS X (não tenho certeza sobre outros sistemas). Portanto, onde você tem o GNUfind
garantido, isso funciona muito bem, mas não é óbvio como adaptar isso, se você não pode garantir que o sistema tenha o GNUfind
instalado. (Ele vai funcionar bem em Linux, que pode ou não pode trabalhar em outro lugar.)find . ! -readable -prune -o -name '*.txt'
parece não funcionar no Ubuntu 14.04 usando o find 4.2.2. Parece inore o-name
. Por alguma razão estranha, eu tenho sucesso comfind . \( ! -readable -prune \) -o -name '*.txt' -print
Se você deseja iniciar a pesquisa a partir da raiz "/", provavelmente verá resultados como:
É por causa da permissão. Para resolver isso:
Você pode usar o comando sudo:
Ele pede a senha do super usuário, quando digitar a senha, você verá o resultado que realmente deseja. Se você não tem permissão para usar o comando sudo, o que significa que você não tem uma senha de superusuário, primeiro peça ao administrador do sistema para adicioná-lo ao arquivo sudoers.
Você pode usar o redirecionamento da Saída de erro padrão de (geralmente exibição / tela) para algum arquivo e evitar ver as mensagens de erro na tela! redirecione para um arquivo especial / dev / null:
Você pode usar o redirecionamento da Saída de erro padrão de (geralmente exibição / tela) para a saída padrão (geralmente exibição / tela) e depois canalizar com o comando grep com o parâmetro -v "invert" para não ver as linhas de saída com 'Permissão negada' pares de palavras:
fonte
sudo find...
Eu tive que usar:
especificando o nome do que eu queria encontrar e dizendo para redirecionar todos os erros para / dev / null
espera ser o local do programa esperado que eu estava procurando.
fonte
expect
. Em vez disso,expect
é simplesmente o nome do arquivo que este comando tentará encontrar.Tubulação
stderr
para/dev/null
usando 2> / dev / nullfind . -name '...' 2>/dev/null
fonte
find . -name '...' -print 2>/dev/null
Você também pode usar os predicados
-perm
e-prune
para evitar descer para diretórios ilegíveis (consulte também Como remover instruções de impressão com "permissão negada" do programa find? - Unix e Linux Stack Exchange ):fonte
-perm -g+r,u+r,o+r
apenas corresponde aos arquivos que têm ar
permissão (leitura) definida para todas as três entidades de segurança do arquivo , o que não tem relação direta com a possibilidade de o usuário atual ler ou não esse arquivo. Ele tem o potencial de perder arquivos que o usuário atual pode ler e corresponder a arquivos que não podem.find . -type d ! \( -perm -u+r -o -perm -g+r -o -perm -o+r \) -prune -o -print
que seria a boa solução.-readable
com-perm
- ver meu comentário anterior e considere este exemplo:echo 'hi' > file; sudo chown nobody:nobody file; sudo chmod o-r file; find file -perm -u=r
impressõesfile
, porque o seu utilizador ler bit é definido, mas ele se relaciona com o donobody
usuário, e não o usuário atual. O usuário atual não pode ler este arquivo; tentecat file
. Veja também: esta resposta minha.Redirecionar erro padrão. Por exemplo, se você estiver usando o bash em uma máquina unix, poderá redirecionar o erro padrão para / dev / null assim:
fonte
Embora as abordagens acima não tratem do caso para o Mac OS X, porque o Mac Os X não suporta
-readable
comutadores, é assim que você pode evitar erros de 'permissão negada' na saída. Isso pode ajudar alguém.find / -type f -name "your_pattern" 2>/dev/null
.Se você estiver usando algum outro comando com
find
, por exemplo, para encontrar o tamanho dos arquivos de determinado padrão em um diretório2>/dev/null
, ainda funcionará como mostrado abaixo.find . -type f -name "your_pattern" -exec du -ch {} + 2>/dev/null | grep total$
.Isso retornará o tamanho total dos arquivos de um determinado padrão. Observe o
2>/dev/null
comando no final do comando find.fonte
2>/dev/null
. Você pode, por favor, explicar a parte-exec du -ch {} + 2>/dev/null | grep total$
.-exec
opção para executar outras ações nos arquivos ou diretórios encontrados porfind
comando.du -ch file_pattern
calcula o tamanho de cada arquivo correspondentefile_pattern
e a última linha dessa saída é o total geral de todos os arquivos correspondentesfile_pattern
. Veja a página de manual paradu
.grep total
apenas filtra a linha que extrai o total geral (que é a última linha).Esses erros são impressos na saída de erro padrão (fd 2). Para filtrá-los, basta redirecionar todos os erros para / dev / null:
ou primeiro, junte-se ao stderr e ao stdout e, em seguida, salve esses erros específicos:
fonte
Resposta simples:
find . > files_and_folders 2>&-
2>&-
fecha (-
) o descritor de arquivo de erro padrão (2
) para que todas as mensagens de erro sejam silenciadas.1
se algumPermission denied
erro ' ' seria impressoResposta robusta para o GNU
find
:find . -type d \! \( -readable -executable \) -prune -print -o -print > files_and_folders
Passe opções extras para
find
isso-prune
(evite a descida para), mas ainda-print
qualquer diretório ( ) que não ( ) tenha permissões e , ou ( ) qualquer outro arquivo.-type
d
\!
-readable
-executable
-o
-print
-readable
e-executable
opções são extensões GNU, não fazem parte do padrão POSIXPermission denied
' em arquivos anormais / corrompidos (por exemplo, consulte o relatório de bug que afeta os sistemas de arquivos montados em contêiner usandolxcfs
<v2.0.5)Resposta robusta que funciona com qualquer compatível com POSIX
find
(GNU, OSX / BSD, etc){ LC_ALL=C find . 3>&2 2>&1 1>&3 > files_and_folders | grep -v 'Permission denied'; [ $? = 1 ]; } 3>&2 2>&1
Use um pipeline para transmitir o fluxo de erro padrão
grep
, removendo todas as linhas que contêm a'Permission denied'
sequência.LC_ALL=C
define o locale POSIX usando uma variável de ambiente ,3>&2 2>&1 1>&3
e3>&2 2>&1
descritores de arquivos duplicados para canalizar o fluxo de erros padrão paragrep
e[ $? = 1 ]
usos[]
para inverter o código de erro retornado porgrep
aproximar o comportamento original defind
.'Permission denied'
erros devido ao redirecionamento de saída (por exemplo, se ofiles_and_folders
arquivo em si não for gravável)fonte
-perm
solução baseada em não vale a pena apresentar, porque mais fundamentalmente do que a citação sugere faz algo diferente do que o pretendido: é um teste puramente centrado em arquivo , relacionado ao proprietário do arquivo e group, nenhum dos quais tem relação garantida com o usuário que está chamando o comando (veja esta resposta minha. Parece que sua solução GNU revisada agora não captura erros de permissão negados decorrentes de arquivos .echo 'hi' > file; sudo chown nobody:nobody file; sudo chmod o-r file; find file -perm -u=r
printsfile
, porque seu bit de leitura do usuário está definido, mas está relacionado aonobody
usuário , não o usuário atual. O usuário atual não pode ler este arquivo; tentecat file
.-perm
isso não funciona para determinar as permissões atuais do usuário. Removida essa alternativa desta resposta.Para evitar apenas os avisos de permissão negada, diga ao find para ignorar os arquivos ilegíveis, removendo-os da pesquisa. Adicione uma expressão como OR à sua localização, como
Isso geralmente diz para (corresponder a um arquivo ilegível e removê-lo da lista) OR (corresponder a um nome como * .jbd e exibi-lo [com ls]) . (Lembre-se de que, por padrão, as expressões são AND juntas, a menos que você use -or.) Você precisa de -ls na segunda expressão, caso contrário, a localização pode adicionar uma ação padrão para mostrar uma das correspondências, o que também mostrará todos os arquivos ilegíveis .
Mas se você está procurando arquivos reais no seu sistema, geralmente não há razão para procurar no / dev, que possui muitos arquivos, portanto, você deve adicionar uma expressão que exclua esse diretório, como:
Então (corresponda arquivo ilegível e remova da lista) OR (corresponda ao caminho / dev e remova da lista) OR (corresponda ao arquivo como * .jbd e exiba-o) .
fonte
usar
É estúpido (porque você eleva a pesquisa) e não seguro, mas muito mais curto para escrever.
fonte
sudo
. Você corre o risco de todo o sistema ser danificado por um bugfind
ou versão maliciosa ou por uma invocação incorreta que escreve algo inesperadamente, o que não poderia acontecer se você executasse isso com privilégios normais.Nenhuma das respostas acima funcionou para mim. Tudo o que encontro na Internet se concentra em: ocultar erros. Nenhum lida adequadamente com o código de retorno / código de saída do processo. Uso o comando find nos scripts do bash para localizar alguns diretórios e depois inspecionar o conteúdo deles. Eu avalio o comando encontrar sucesso usando o código de saída: um valor zero funciona, caso contrário, falha.
A resposta fornecida acima por Michael Brux funciona algumas vezes. Mas eu tenho um cenário em que falha! Eu descobri o problema e o consertei. Preciso remover arquivos quando:
Veja a questão principal aqui é: AND / OR. Uma boa sequência de condições sugerida que li é:
Isso nem sempre funciona. Isso significa que uma ameixa é acionada quando uma correspondência é:
Essa sequência de expressões falha quando o acesso de leitura é concedido, mas nenhum acesso de execução é.
Após alguns testes, percebi isso e mudei minha solução de script de shell para:
A chave aqui é colocar o "não verdadeiro" para uma expressão combinada:
Caso contrário, ele não terá acesso total, o que significa: removê-lo. Isso provou funcionar para mim em um cenário em que as soluções sugeridas anteriormente falharam.
A seguir, forneço detalhes técnicos para perguntas na seção de comentários. Peço desculpas se os detalhes forem excessivos.
fonte
nice
efind $HOME -maxdepth 5 -follow ...
?${m_find_name}
), e contém várias opções que não são relevantes para a questão (nice
,/home*
,-maxdepth 5
,-follow
). Adicionei uma resposta que aborda a questão específica de 'filtrar diretórios legíveis, mas não executáveis' de forma mais concisa, enquanto permanece de uso geral.Você pode usar o grep -v invert-match
como isso:
Deve à magia
fonte
- = Para MacOS = -
Faça um novo comando usando o alias: basta adicionar na linha ~ / .bash_profile:
e na nova janela do Terminal, você pode chamá-lo:
fonte
Se você estiver usando CSH ou TCSH, aqui está uma solução:
Se você deseja saída para o terminal:
No entanto, como a FAQ "csh-whynot" descreve, você não deve usar o CSH.
fonte