Nota:
* Questa risposta probabilmente va più in profondità rispetto al caso d'uso e find 2>/dev/nullpuò 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 findchiamate 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 è bashozsh , c'è una soluzione che è robusta pur essendo ragionevolmente semplice , usando solo findfunzionalità conformi a POSIX ; mentre di per bashsé 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 grepoutput possano arrivare dopo il find completamento, perché il comando generale non attende il completamento del comando interno >(...). In bash, puoi impedirlo aggiungendo | catil 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>>(...)
bashzshksh2> >(...)ksh 93u+
grep -v 'Permission denied'filtra out ( -v) tutte le linee (dal findflusso stderr del comando) che contengono la frase Permission deniede visualizza le righe rimanenti stderr ( >&2).
Questo approccio è:
robusto : grepviene 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 : findil 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>&1deve venire prima .
Catturare l'output di stdout in un file in primo piano consente 2>&1di inviare solo messaggi di errore attraverso la pipeline, che greppossono quindi operare senza ambiguità.
L' unico inconveniente è che il codice di complessiva di uscita sarà il grepdel comando , non finds', 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, findil 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 findcodice 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 1tal caso, 0altrimenti.
In altre parole: il codice di uscita ora riflette il vero intento del comando: 0viene segnalato success ( ), se non si sono verificati errori o si sono verificati solo errori negati.
Questo è probabilmente anche meglio del semplice passaggio finddel 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 3viene utilizzato per scambiare temporaneamente stdout ( 1) e stderr ( 2), in modo che solo i messaggi di errore possano essere inviati greptramite stdout.
Senza questi reindirizzamenti, sia i dati (percorsi dei file) che i messaggi di errore verrebbero inviati greptramite stdout e grepquindi 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 deniederrori possono ancora emergere: find ! -readable -prunesegnala tali errori per gli elementi figlio delle directory per i quali l'utente attuale dispone rdell'autorizzazione, ma manca l' xautorizzazione (eseguibile). Il motivo è che, poiché la directory stessa è leggibile, -prunenon viene eseguita e il tentativo di scendere in quella directory attiva quindi i messaggi di errore. Detto questo, il caso tipico è che rmanchi 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 findcomando, 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
-namefiltro, 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_filecorre 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:?