Nota:
* Questa risposta probabilmente va più in profondità rispetto al caso d'uso e find 2>/dev/null
può essere abbastanza buona in molte situazioni. Potrebbe essere ancora interessante per una prospettiva multipiattaforma e per la sua discussione di alcune tecniche di shell avanzate nell'interesse di trovare una soluzione il più robusta possibile, anche se i casi a cui si può far fronte possono essere in gran parte ipotetici.
* Se il tuo sistema è configurato per mostrare messaggi di errore localizzati , aggiungi il prefisso delle find
chiamate in basso con LC_ALL=C
( LC_ALL=C find ...
) per assicurarti che i messaggi in inglese vengano segnalati, in modo che grep -v 'Permission denied'
funzioni come previsto. Invariabilmente, però, eventuali messaggi di errore che fanno ottenere visualizzati saranno quindi in inglese.
Se la tua shell è bash
ozsh
, c'è una soluzione che è robusta pur essendo ragionevolmente semplice , usando solo find
funzionalità conformi a POSIX ; mentre di per bash
sé non fa parte di POSIX, la maggior parte delle piattaforme Unix moderne ne è dotata, rendendo questa soluzione ampiamente portatile:
find . > files_and_folders 2> >(grep -v 'Permission denied' >&2)
Nota: c'è una piccola possibilità che alcuni degli grep
output possano arrivare dopo il find
completamento, perché il comando generale non attende il completamento del comando interno >(...)
. In bash
, puoi impedirlo aggiungendo | cat
il comando.
>(...)
è una sostituzione del processo di output (usata raramente) che consente di reindirizzare l'output (in questo caso, stderr output ( ) allo stdin del comando all'interno .
Oltre a e , li supporta anche in linea di principio , ma provando a combinarli con il reindirizzamento da stderr , come si fa qui ( ), sembra essere silenziosamente ignorato (in ).2>
>(...)
bash
zsh
ksh
2> >(...)
ksh 93u+
grep -v 'Permission denied'
filtra out ( -v
) tutte le linee (dal find
flusso stderr del comando) che contengono la frase Permission denied
e visualizza le righe rimanenti stderr ( >&2
).
Questo approccio è:
robusto : grep
viene applicato solo ai messaggi di errore (e non a una combinazione di percorsi di file e messaggi di errore, che potenzialmente portano a falsi positivi) e vengono trasmessi a stderr messaggi di errore diversi da quelli negati dalle autorizzazioni.
side-effect free : find
il codice di uscita è preservato: l'impossibilità di accedere ad almeno uno degli elementi del filesystem riscontrati provoca il codice di uscita 1
(anche se ciò non ti dirà se si sono verificati (anche) errori diversi da quelli negati dal permesso).
Soluzioni conformi a POSIX:
Le soluzioni completamente conformi a POSIX presentano limitazioni o richiedono un lavoro aggiuntivo.
Se find
's uscita deve essere catturato in un file di ogni caso (o soppresso del tutto), allora la soluzione a base di gasdotto dalla risposta di Jonathan Leffler è semplice, robusto, e POSIX-compliant:
find . 2>&1 >files_and_folders | grep -v 'Permission denied' >&2
Nota che l'ordine dei reindirizzamenti conta: 2>&1
deve venire prima .
Catturare l'output di stdout in un file in primo piano consente 2>&1
di inviare solo messaggi di errore attraverso la pipeline, che grep
possono quindi operare senza ambiguità.
L' unico inconveniente è che il codice di complessiva di uscita sarà il grep
del comando , non find
s', che in questo caso significa: se non ci sono nessun errori a tutti o solo errori di autorizzazione negata, il codice di uscita verrà 1
(segnalamento fallimento ), in caso contrario ( errori diversi da quelli negati dal permesso) 0
- che è l'opposto dell'intento.
Detto questo, find
il codice di uscita viene utilizzato raramente in ogni caso , poiché spesso trasmette poche informazioni al di là di un fallimento fondamentale come il passaggio di un percorso inesistente.
Tuttavia, il caso specifico di anche solo alcunidei percorsi di input inaccessibili a causa della mancanza di autorizzazioni si riflette nel find
codice di uscita (sia in GNU che in BSD find
): se si verifica un errore negato alle autorizzazioni per uno qualsiasi dei file elaborati, il codice di uscita è impostato su 1
.
La seguente variazione si rivolge a:
find . 2>&1 >files_and_folders | { grep -v 'Permission denied' >&2; [ $? -eq 1 ]; }
Ora, il codice di uscita indica se si sono verificati errori diversi Permission denied
: in 1
tal caso, 0
altrimenti.
In altre parole: il codice di uscita ora riflette il vero intento del comando: 0
viene segnalato success ( ), se non si sono verificati errori o si sono verificati solo errori negati.
Questo è probabilmente anche meglio del semplice passaggio find
del codice di uscita, come nella soluzione in alto.
gniourf_gniourf nei commenti propone una generalizzazione (ancora conforme a POSIX) di questa soluzione usando reindirizzamenti sofisticati , che funziona anche con il comportamento predefinito di stampa dei percorsi dei file su stdout :
{ find . 3>&2 2>&1 1>&3 | grep -v 'Permission denied' >&3; } 3>&2 2>&1
In breve: il descrittore di file personalizzato 3
viene utilizzato per scambiare temporaneamente stdout ( 1
) e stderr ( 2
), in modo che solo i messaggi di errore possano essere inviati grep
tramite stdout.
Senza questi reindirizzamenti, sia i dati (percorsi dei file) che i messaggi di errore verrebbero inviati grep
tramite stdout e grep
quindi non sarebbero in grado di distinguere tra messaggio di errore Permission denied
e un file (ipotetico) il cui nome contiene la frase Permission denied
.
Come nella prima soluzione, tuttavia, il codice di uscita segnalato sarà grep
"non find
", ma è possibile applicare la stessa correzione di cui sopra.
Note sulle risposte esistenti:
Ci sono diversi punti da notare su risposta di Michael Brux , find . ! -readable -prune -o -print
:
Richiede GNU find
; in particolare, non funzionerà su macOS. Ovviamente, se hai solo bisogno del comando per lavorare con GNU find
, questo non sarà un problema per te.
Alcuni Permission denied
errori possono ancora emergere: find ! -readable -prune
segnala tali errori per gli elementi figlio delle directory per i quali l'utente attuale dispone r
dell'autorizzazione, ma manca l' x
autorizzazione (eseguibile). Il motivo è che, poiché la directory stessa è leggibile, -prune
non viene eseguita e il tentativo di scendere in quella directory attiva quindi i messaggi di errore. Detto questo, il caso tipico è che r
manchi l' autorizzazione.
Nota: il punto seguente è una questione di filosofia e / o caso d'uso specifico e potresti decidere che non è pertinente per te e che il comando si adatta bene alle tue esigenze, soprattutto se semplicemente stampando i percorsi è tutto ciò che fai:
- Se si concettualizza il filtraggio dei messaggi di errore negati all'autorizzazione un'attività separata che si desidera poter applicare a qualsiasi
find
comando, l'approccio opposto di prevenzione proattiva degli errori negati all'autorizzazione richiede l'introduzione di "rumore" nel find
comando, che introduce anche complessità e insidie logiche .
- Ad esempio, il commento più votato sulla risposta di Michael (al momento della stesura di questo documento) tenta di mostrare come estendere il comando includendo un
-name
filtro, come segue:
find . ! -readable -prune -o -name '*.txt'
Questo, tuttavia, non funziona come previsto, poiché -print
è richiesta l' azione finale (una spiegazione può essere trovata in questa risposta ). Tali sottigliezze possono introdurre bug.
La prima soluzione in risposta di Jonathan Leffler , find . 2>/dev/null > files_and_folders
, come egli stesso afferma, zittisce ciecamente tutti i messaggi di errore (e la soluzione è ingombrante e non pienamente affidabile, come egli spiega anche). In termini pragmatici , tuttavia, è la soluzione più semplice , poiché potresti accontentarti di presumere che tutti gli errori siano legati alle autorizzazioni.
La risposta di foschia , sudo find . > files_and_folders
, è conciso e pragmatico, ma mal consigliato per altro che solamente la stampa i nomi dei file , per motivi di sicurezza: perché si sta eseguendo come radice dell'utente ", si rischia di avere l'intero sistema di essere incasinato da un bug nel ritrovamento o una versione malevola o una chiamata errata che scrive qualcosa di inaspettatamente, il che non potrebbe accadere se lo eseguissi con privilegi normali "(da un commento sulla risposta di mist da parte di tripleee ).
La seconda soluzione nella risposta di viraptor , find . 2>&1 | grep -v 'Permission denied' > some_file
corre il rischio di falsi positivi (a causa dell'invio di un mix di stdout e stderr attraverso la pipeline) e, potenzialmente, invece di segnalare errori non negati per ammissione tramite stderr, li cattura lungo i percorsi di output nel file di output.
find . 2>&1 > files_and_folders | grep -v 'Permission denied' >&2
:?