Comment puis-je exclure tous les messages "permission denied" de "find"?

j'ai besoin de masquer tous les permission denied messages à partir de:

find . > files_and_folders

j'expérimente quand un tel message apparaît. Je dois rassembler tous les dossiers et les fichiers, à laquelle il ne se pose pas.

est-il possible d'Orienter les niveaux de permission vers le fichier files_and_folders ?

Comment puis-je Cacher les erreurs en même temps?

693
demandé sur Jahid 2009-04-18 01:54:07

18 réponses

Note:

* Cette réponse va probablement plus loin que le cas d'utilisation le justifie, et find 2>/dev/null peut être suffisant dans de nombreuses situations. Il peut encore être intéressant pour une perspective inter-plate-forme et pour sa discussion de certaines techniques avancées de shell dans l'intérêt de trouver une solution qui est aussi robuste que possible, même si les cas protégés contre peuvent être largement hypothétique.

* Si votre système est configuré pour afficher localisé messages d'erreur , préfixer les appels find ci-dessous avec LC_ALL=C ( LC_ALL=C find ... ) pour s'assurer que anglais messages sont signalés, de sorte que grep -v 'Permission denied' fonctionne comme prévu. Invariablement, cependant, les messages d'erreur faire affiché sera ensuite en anglais.

si votre est bash ou zsh , il y a une solution qui est robuste tout en étant raisonnablement simple , en utilisant seulement conforme POSIX find caractéristiques ; alors que bash elle-même ne fait pas partie de POSIX, la plupart des plates-formes Unix modernes viennent avec elle, ce qui rend cette solution largement portable:

find . > files_and_folders 2> >(grep -v 'Permission denied' >&2)

Note: Il y a une petite chance que certains de grep de sortie peut arriver après find complète, parce que la commande globale n'attend pas la commande à l'intérieur de >(...) pour finir. Dans bash , vous pouvez empêcher cela en ajoutant | cat à la commande.

  • >(...) est un (rarement utilisé) sortie substitution de processus qui permet de rediriger la sortie (dans ce cas, stderr sortie ( 2> ) vers le stdin de la commande à l'intérieur de >(...) .

    En plus de bash , et zsh , ksh les supporte aussi en principe , mais en essayant de les combiner avec une redirection de stderr , comme c'est fait ici ( 2> >(...) ), semble être silencieusement ignoré (dans ksh 93u+ ).

    • grep -v 'Permission denied' filters out ( -v ) toutes les lignes (à partir du find command's stderr stream) qui contient la phrase Permission denied et affiche les lignes restantes vers stderr ( >&2 ).

Cette approche est:

  • robuste : grep est seulement appliqué à messages d'erreur (et non à une combinaison de chemins de fichier et messages d'erreur, conduisant potentiellement à des faux positifs), et messages d'erreur autres que ceux qui ne sont pas autorisés sont transmis à stderr.

  • sans effet secondaire : find le code de sortie de "est préservé: l'impossibilité d'accéder à au moins un des éléments du système de fichiers rencontrés se traduit par le code de sortie 1 (bien que cela ne vous dira pas si les erreurs autre que celles avec permission refusée se sont produites (aussi)).


POSIX-compliant solutions:

Les solutions entièrement conformes à la norme

entièrement conformes à la norme POSIX ont des limites ou nécessitent des travaux supplémentaires.

si la sortie de find doit être saisie dans un fichier de toute façon (ou supprimée complètement), alors la solution basée sur le pipeline de réponse de Jonathan Leffler est simple, robuste et conforme à POSIX:

find . 2>&1 >files_and_folders | grep -v 'Permission denied' >&2

Notez que l'ordre des redirections questions: 2>&1 doit venir première .

Capture stdout dans un fichier à l'avant permet de 2>&1 envoyer seulement "1519860920 des messages d'erreur" à travers le pipeline, qui grep peut alors fonctionner sans ambiguïté.

le seul inconvénient est que le code de sortie global sera le grep commande , pas find 's, qui dans ce cas signifie: s'il y a Non erreurs du tout ou seulement permission-denied errors, the exit code will be 1 (signaling failure ), sinon (erreurs autres que permission-denied ones) 0 - ce qui est le contraire de l'intention.

cela dit, find code de sortie est rarement utilisé , car il communique souvent peu d'information au-delà de défaillance" fondamentale telle que le passage d'un chemin inexistant.

Cependant, le cas spécifique de ne serait-ce que quelque des chemins d'entrée étant inaccessible en raison du manque de permissions est reflété dans le code de sortie de find (à la fois dans GNU et BSD find ): si une erreur de permissions-denied se produit pour toute de la fichiers traités, le code de sortie est défini à 1 .

la variation suivante tient compte de cela:

find . 2>&1 >files_and_folders | { grep -v 'Permission denied' >&2; [ $? -eq 1 ]; }

maintenant, le code de sortie indique si des erreurs autres que Permission denied se sont produites: 1 si oui, 0 autrement.

En d'autres termes: le code de sortie reflète désormais la véritable intention de la commande: succès ( 0 ) est signalé, si pas d'erreurs ou seulement des erreurs ont été commises.

C'est sans doute encore mieux que de simplement passer le code de sortie de find , comme dans la solution en haut.


gniourf_gniourf dans les commentaires propose une (encore conforme POSIX) généralisation de cette solution en utilisant des redirections sophistiquées , qui fonctionne même avec le comportement par défaut de l'impression des chemins de fichier vers stdout :

{ find . 3>&2 2>&1 1>&3 | grep -v 'Permission denied' >&3; } 3>&2 2>&1

en bref: le descripteur de fichier personnalisé 3 est utilisé pour permuter Temporairement stdout ( 1 ) et stderr ( 2 ), de sorte que les messages d'erreur seul peuvent être pipés à grep via stdout.

sans ces redirections, les deux données (chemins de fichier) et messages d'erreur serait acheminé à grep via stdout, et grep ne serait alors pas en mesure de distinguer entre message d'erreur Permission denied et un (hypothétique) fichier dont le nom contient l'expression Permission denied .

Comme dans la première solution, cependant, le code de sortie signalé sera grep , pas find , mais le même correctif comme ci-dessus peuvent être appliquées.


Notes sur les réponses:

  • il y a plusieurs points à noter au sujet de réponse de Michael Brux , find . ! -readable -prune -o -print :

    • Il faut GNU find ; notamment, il ne fonctionnera pas sur macOS. Bien sûr , si vous avez seulement besoin de la commande pour travailler avec GNU find , ce ne sera pas un problème pour vous.

    • Certains Permission denied erreurs encore surface: find ! -readable -prune les rapports de ces erreurs pour le enfant éléments de répertoires pour lesquels l'utilisateur actuel n'ont r la permission, mais manque de x (exécutable) autorisation. La raison est que parce que le répertoire lui-même est lisible, -prune n'est pas exécuté, et la tentative de descendre dans ce répertoire déclenche alors les messages d'erreur. Cela dit, le cas typique est pour la permission r d'être absent.

    • Note: le point suivant est une question de philosophie et / ou de cas d'utilisation spécifique, et vous pouvez décider qu'il n'est pas pertinent pour vous et que la commande répond bien à vos besoins, surtout si simplement impression les chemins est tout ce que vous faites:

      • Si vous conceptualiser le filtrage de l'autorisation, de refus d'erreur les messages d'un séparé la tâche que vous voulez être en mesure de s'appliquer à tout "151950920 de la commande", puis à l'opposé de l'approche de façon proactive prévention l'autorisation des erreurs de refus nécessite l'introduction de "bruit" dans le "151950920 de la commande", qui introduit aussi la complexité et logique pièges .
      • par exemple, le commentaire le plus voté sur la réponse de Michael (en date de cette écriture) tente de montrer comment étendre la commande en incluant un filtre -name , comme suit:

        find . ! -readable -prune -o -name '*.txt'

        Cela, cependant, ne fonctionne pas comme prévu, parce que l'arrière -print action est requis (an explication peut être trouvée dans cette réponse ). Ces subtilités peuvent introduire des bogues.
  • La première solution dans le Jonathan Leffler la réponse de , find . 2>/dev/null > files_and_folders , comme il l'a lui-même déclare, à l'aveuglette silences tous messages d'erreur (et la solution de contournement est lourd et n'est pas entièrement solide, comme il l'a aussi expliquer.) pragmatiquement parlant , cependant , c'est la solution la plus simple , car vous pouvez vous contenter de supposer que toutes les erreurs seraient liées à la permission.

  • réponse de mist , sudo find . > files_and_folders , est concis et pragmatique, mais mal avisé pour tout autre que simplement impression noms de fichiers , pour la sécurité raisons: parce que vous êtes en cours d'exécution en tant que root user, "vous risquez d'avoir tout votre système être perturbé par un bug dans find ou une version malveillante, ou une invocation incorrecte qui écrit quelque chose de manière inattendue, ce qui ne pourrait pas se produire si vous avez couru cela avec des privilèges normaux" (d'un commentaire sur la réponse de mist par tripleee ).

  • La 2ème solution dans viraptor réponse , find . 2>&1 | grep -v 'Permission denied' > some_file court le risque de faux positifs (en raison de l'envoi d'un mélange de stdout et de stderr à travers le pipeline), et, potentiellement, au lieu de signaler non - permission-denied errors via stderr, les capture le long des chemins de sortie dans le fichier de sortie.

170
répondu mklement0 2017-05-23 12:26:38

Utiliser:

find . 2>/dev/null > files_and_folders

cela cache non seulement les erreurs Permission denied , bien sûr, mais tous les messages d'erreur.

si vous voulez vraiment garder d'autres erreurs possibles, comme trop de sauts sur un lien symbolique, mais pas la permission refusée ceux, alors vous auriez probablement à prendre une supposition volante que vous n'avez pas beaucoup de fichiers appelés 'permission refusée' et essayer:

find . 2>&1 | grep -v 'Permission denied' > files_and_folders

Si vous strictement vous voulez filtrer l'erreur standard, vous pouvez utiliser la construction plus élaborée:

find . 2>&1 > files_and_folders | grep -v 'Permission denied' >&2

la redirection d'e/s sur la commande find est: 2>&1 > files_and_folders | . Le tuyau redirige la sortie standard vers la commande grep et est appliqué en premier. Le 2>&1 envoie l'erreur standard au même endroit que la sortie standard (le tuyau). Le > files_and_folders envoie la sortie standard (mais pas l'erreur standard) à un fichier. Le résultat net est que les messages écrits à la norme les erreurs sont envoyées dans le tuyau et la sortie régulière de find est écrite dans le fichier. Le grep filtre la sortie standard (vous pouvez décider à quel point vous voulez qu'elle soit sélective, et peut avoir à changer l'orthographe en fonction de la locale et O/S) et le >&2 final signifie que les messages d'erreur survivants (écrits à la sortie standard) aller à l'erreur standard une fois de plus. La redirection peut être considéré comme facultatif à la borne, mais serait une très bonne idée de l'utiliser dans un script, de sorte que les messages d'erreur apparaissent sur l'erreur standard.

il y a des variations infinies sur ce thème, selon ce que vous voulez faire. Cela fonctionnera sur N'importe quelle variante D'Unix avec N'importe quel dérivé de shell Bourne (Bash, Korn, ...) et n'importe quelle version find .

Si vous souhaitez adapter à la version spécifique de find que vous avez sur votre système, il peut y avoir d'autres options disponibles. GNU find en particulier a une myriade d'options non disponibles dans d'autres versions - voir la réponse actuellement acceptée pour un tel ensemble d'options.

501
répondu Jonathan Leffler 2017-12-19 19:30:23

Utiliser:

find . ! -readable -prune -o -print

ou plus généralement

find <paths> ! -readable -prune -o <other conditions like -name> -print
  • pour éviter "Permission refusée"
  • et ne suppriment pas les messages d'erreur (autres)
  • et obtenir le statut de sortie 0 ("tous les fichiers sont traités avec succès")

fonctionne avec: find (GNU findutils) 4.4.2. Historique:

  • l'essai -readable correspond aux fichiers lisibles. L'opérateur ! renvoie true, lorsque le test est faux. Et ! -readable correspond à des répertoires (&fichiers) non lisibles.
  • l'action -prune ne descend pas dans directory.
  • ! -readable -prune peut être traduit en: si le répertoire n'est pas lisible, ne pas y descendre.
  • le test -readable prend en compte les listes de contrôle d'accès et autres permissions artéfacts que le -perm le test ignore.

Voir aussi find (1) page de manuel pour beaucoup plus de détails.

253
répondu Michael Brux 2018-08-03 17:39:27

si vous voulez lancer la recherche à partir de la racine "/", vous verrez probablement sortir quelque chose comme:

find: /./proc/1731/fdinfo: Permission denied
find: /./proc/2032/task/2032/fd: Permission denied

c'est à cause de la permission. Pour résoudre ce problème:

  1. vous pouvez utiliser la commande sudo: sudo find /. -name 'toBeSearched.file' . il demande le mot de passe du super utilisateur, quand entrez le mot de passe, vous verrez le résultat que vous voulez vraiment.

  2. vous pouvez utiliser rediriger la sortie D'erreur Standard de (généralement Display / Screen) à certains fichiers et éviter de voir les messages d'erreur sur l'écran! rediriger vers un fichier spécial /dev/null :

    find /. -name 'toBeSearched.file' 2>/dev/null
    
  3. vous pouvez utiliser rediriger la sortie D'erreur Standard de (généralement affichage / écran) vers la sortie Standard (généralement affichage / écran), puis pipe avec la commande grep avec le paramètre-v "inverse" pour ne pas voir les lignes de sortie qui ont' Permission denied 'des paires de mots:

    find /. -name 'toBeSearched.file' 2>&1 | grep -v 'Permission denied'
    
105
répondu Fatih Aksu 2014-12-31 18:54:48

j'ai dû utiliser:

find / -name expect 2>/dev/null

spécifiant le nom de ce que je voulais trouver et lui disant de rediriger toutes les erreurs vers /dev / null

expect est l'emplacement du programme expect que je cherchais.

83
répondu Jeremy 2013-03-31 03:27:02

Pipe stderr à /dev/null à l'aide de 2>/dev/null

find . -name '...' 2>/dev/null

50
répondu Matt 2014-07-30 18:46:48

vous pouvez également utiliser les prédicats -perm et -prune pour éviter de descendre dans des répertoires illisibles (voir aussi Comment puis-je supprimer les instructions" permission denied " du programme find? - Unix & Linux Stack Exchange ):

find . -type d ! -perm -g+r,u+r,o+r -prune -o -print > files_and_folders
29
répondu sdaau 2017-04-13 12:36:27

rediriger l'erreur standard. Par exemple, si vous utilisez bash sur une machine unix, vous pouvez rediriger l'erreur standard vers /dev/null comme ceci:

find . 2>/dev/null >files_and_folders
22
répondu Jason Coco 2009-04-17 21:57:44

alors que les approches ci-dessus ne traitent pas le cas de Mac OS X parce que Mac Os X ne supporte pas le commutateur -readable c'est comme ça que vous pouvez éviter les erreurs "Permission denied" dans votre sortie. Cela pourrait aider quelqu'un.

find / -type f -name "your_pattern" 2>/dev/null .

si vous utilisez une autre commande avec find , par exemple, pour trouver la taille des fichiers de certains motifs dans un répertoire 2>/dev/null fonctionnerait toujours comme indiqué ci-dessous.

find . -type f -name "your_pattern" -exec du -ch {} + 2>/dev/null | grep total$ .

renvoie la taille totale des fichiers d'un motif donné. Notez le 2>/dev/null à la fin de la commande rechercher.

19
répondu Bunti 2016-02-02 09:55:44

ces erreurs sont imprimées sur la sortie standard error (fd 2). Pour les filtrer, redirigez simplement toutes les erreurs vers /dev / null:

find . 2>/dev/null > some_file

ou d'abord joindre stderr et stdout et ensuite grep ces erreurs spécifiques:

find . 2>&1 | grep -v 'Permission denied' > some_file
13
répondu viraptor 2009-04-17 22:00:10

réponse Simple:

find . > files_and_folders 2>&-

2>&- ferme ( - ) le descripteur de fichier d'erreur standard ( 2 ) de sorte que tous les messages d'erreur sont réduits au silence.

  • le code de sortie sera toujours 1 s'il y a lieu" Permission denied "les erreurs seraient autrement imprimées

réponse robuste pour GNU find :

find . -type d \! \( -readable -executable \) -prune -print -o -print > files_and_folders

passer les options supplémentaires à find que -prune (empêcher de descendre dans) mais tout de même -print n'importe quel répertoire ( -type d ) ce n'est pas ( \! ) ont à la fois les autorisations -readable et -executable , ou ( -o ) -print tout autre dossier.

réponse robuste qui fonctionne avec N'importe quel compatible 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

utilisez un pipeline pour passer le flux d'erreur standard à grep , suppression de toutes les lignes contenant la chaîne 'Permission denied' .

LC_ALL=C ensembles le POSIX locale utilisant une variable d'environnement , 3>&2 2>&1 1>&3 et 3>&2 2>&1 duplicate file descriptors pour conduire le flux d'erreur standard à grep , et [ $? = 1 ] utilise [] pour inverser le code d'erreur retourné par grep pour se rapprocher du comportement original de find .

  • filtrera également toute erreur 'Permission denied' due à une redirection de sortie (par exemple, si le fichier files_and_folders lui-même n'est pas accessible en écriture)
10
répondu wjordan 2016-12-30 03:42:35

pour éviter juste la permission a refusé les Avertissements, dire à find d'ignorer les fichiers illisibles en les élaguant de la recherche. Ajouter une expression comme ou à votre find, telle que

find / \! -readable -prune -o -name '*.jbd' -ls

Ce la plupart du temps dit (match un fichier illisible et le tailler à partir de la liste) OU (correspondance avec un nom comme *.jbd et de l'afficher [ls]) . (Rappelez-vous que par défaut, la expressions ET serions ensemble, sauf si vous utilisez ou.) Vous avez besoin de l'option-ls dans la seconde expression ou alors find peut ajouter une action par défaut pour afficher l'une ou l'autre correspondance, ce qui vous montrera aussi tous les fichiers illisibles.

mais si vous cherchez des fichiers réels sur votre système, il n'y a généralement aucune raison de chercher dans /dev, qui a beaucoup de fichiers, donc vous devriez ajouter une expression qui exclut ce répertoire, comme:

find / -mount \! -readable -prune  -o  -path /dev -prune  -o  -name '*.jbd' -ls

Donc (match fichier illisible et prune de la liste) ou (match path /dev et prune de la liste) ou (match file like *.jbd et l'afficher) .

4
répondu simpleuser 2014-09-16 00:59:49

utiliser

sudo find / -name file.txt

c'est stupide (parce que vous élevez la recherche) et non sûr, mais beaucoup plus court pour écrire.

4
répondu mist 2014-12-16 12:01:46

aucune des réponses ci-dessus n'a fonctionné pour moi. Tout ce que je trouve sur Internet se concentre sur: Cacher les erreurs. Aucun gère correctement le processus de retour de code / sortie de code. J'utilise la commande find dans les scripts bash pour localiser certains répertoires et ensuite inspecter leur contenu. J'évalue la commande find success en utilisant le code exit: une valeur zéro fonctionne, sinon échoue.

Le réponse ci-dessus par Michael Brux fonctionne parfois. Mais Je avoir un scénario dans lequel il ne! J'ai découvert le problème et résolu moi-même. Je dois tailler les fichiers quand:

it is a directory AND has no read access AND/OR has no execute access

voir la question clé ici est: et/ou. Une bonne séquence de condition suggérée que j'ai Lu est:

-type d ! -readable ! -executable -prune

Cela ne fonctionne pas toujours. Cela signifie qu'un prune est déclenché quand une correspondance est:

it is directory AND no read access AND no execute access

cette séquence d'expressions échoue lorsque l'accès en lecture est accordé mais qu'aucun accès en exécution ne l'est.

après quelques tests j'ai réalisé à ce sujet et j'ai changé ma solution de script shell en:

nice find / home* / - maxdepth 5-follow \

    \( -type d -un ! \ (lisible par un exécutable \) \) -prune \

    -o \

    \( -type d -un -lisible -un -exécutable -un -nom "${m_find_name}" \) -impression

La clé ici est de placer le "pas vrai" pour une expression:

has read access AND has execute access

sinon il n'a pas un accès complet, ce qui signifie: taillez-le. Cela a fonctionné pour moi dans un scénario où les solutions suggérées précédemment ont échoué.

je fournis ci-dessous des détails techniques pour les questions dans la section des commentaires. Je m'excuse si les détails sont excessifs.

  • ¿Pourquoi utiliser la commande nice? J'ai eu l' idée ici . Au départ, j'ai pensé qu'il serait bien de réduire la priorité des processus lorsque l'on regarde tout un système de fichiers. J'ai réalisé que cela n'avait aucun sens pour moi, car mon script est limité à quelques répertoires. J'ai réduit-maxdepth à 3.
  • ¿Pourquoi chercher dans /home*/? Ce n'est plus pertinente pour ce thread. J'installe toutes les applications à la main via le code source compiler avec des utilisateurs non privilégiés (pas root). Ils sont installés dans "/ home". Je peux avoir plusieurs binaires. et des versions vivant ensemble. Je dois localiser tous les répertoires, inspecter et sauvegarder de façon maître-esclave. Je peux avoir plus d'un "/home" (plusieurs disques tournant sur un serveur dédié).
  • ¿Pourquoi utiliser-suivre? Les utilisateurs peuvent créer des liens symboliques vers des répertoires. Son utilité dépend, j'ai besoin de noter les chemins absolus trouvés.
2
répondu Jordi Ferran 2017-05-23 11:47:31

vous pouvez utiliser le grep-v invert-match

-v, --invert-match        select non-matching lines

comme ceci:

find . > files_and_folders
cat files_and_folders | grep -v "permission denied" > files_and_folders

devrait à la magie

2
répondu Leonardo Hermoso 2016-12-27 04:02:43

- = Pour MacOS= -

crée une nouvelle commande en utilisant alias: il suffit d'ajouter ~/.bash_profile ligne:

alias search='find / -name $file 2>/dev/null'

et dans la nouvelle fenêtre du Terminal vous pouvez l'appeler:

$ file=<filename or mask>; search

par exemple:

$ fichier=etc; la recherche

0
répondu Jan aka uptech 2017-08-09 23:10:28

si vous utilisez CSH ou TCSH, voici une solution:

( find . > files_and_folders ) >& /dev/null

si vous voulez la sortie vers le terminal:

( find . > /dev/tty ) >& /dev/null

cependant, comme le décrit la FAQ "csh-whynot", vous ne devez pas utiliser CSH.

0
répondu Kayle Sawyer 2018-01-16 18:13:23

Vous aussi une solution facile à mettre vos résultats de recherche dans un fichier.

trouver . - nom 'NameOfSearchedFile' >> résultats.txt

-1
répondu korodani 2017-05-17 12:33:28