Comment puis-je exclure tous les messages de «permission refusée» de «trouver»?

Je dois cacher tous les messages de permission refusés de:

find . > files_and_folders 

J’expérimente quand un tel message apparaît. Je dois rassembler tous les dossiers et fichiers auxquels il ne se trouve pas.

Est-il possible de diriger les niveaux d’autorisation vers le fichier files_and_folders ?

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

Remarque:
* Cette réponse va probablement plus loin que les warrants d’utilisation, et find 2>/dev/null peut suffire dans de nombreuses situations. Il peut encore être intéressant pour une perspective multi-plateforme et pour la discussion de certaines techniques de shell avancées dans le but de trouver une solution aussi robuste que possible, même si les cas de figure peuvent être largement hypothétiques.
* Si votre système est configuré pour afficher des messages d’erreur localisés , préfixez les appels de find ci-dessous avec LC_ALL=C ( LC_ALL=C find ... ) pour vous assurer que les messages en anglais sont signalés afin que grep -v 'Permission denied' fonctionne comme prévu . Invariablement, cependant, tous les messages d’erreur affichés seront également en anglais.

Si votre shell est bash ou zsh , il existe une solution robuste tout en étant relativement simple , utilisant uniquement des fonctions de find compatibles POSIX ; alors que bash lui-même ne fait pas partie de POSIX, la plupart des plates-formes Unix modernes vont avec, ce qui rend cette solution largement portable:

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

Note: Il est peu probable qu’une partie de la sortie de grep arrive après la fin de la find , car la commande globale n’attend pas la fin de la commande >(...) . En bash , vous pouvez empêcher cela en ajoutant | cat | cat à la commande.

  • >(...) est une substitution de processus de sortie (rarement utilisée) qui permet de redirect la sortie (dans ce cas, la sortie stderr ( 2> ) vers le stdin de la commande inside >(...) .
    En plus de bash et de zsh , ksh supporte également en principe, mais essayer de les combiner avec la redirection depuis stderr , comme cela est fait ici ( 2> >(...) ksh 93u+ 2> >(...) ), semble être ignoré silencieusement (dans ksh 93u+ ).

    • grep -v 'Permission denied' filtre ( -v ) toutes les lignes (du stream stderr de la commande find ) contenant la phrase Permission denied et affiche les lignes restantes dans stderr ( >&2 ).

Cette approche est la suivante:

  • robust : grep s’applique uniquement aux messages d’erreur (et non à une combinaison de chemins d’access et de messages d’erreur pouvant mener à des faux positifs) et les messages d’erreur autres que ceux pour lesquels l’autorisation est refusée sont transmis à stderr.

  • effet secondaire libre : le code de sortie de find est préservé: l’impossibilité d’accéder à au moins un des éléments du système de fichiers rencontrés entraîne le code de sortie 1 (bien que cela ne vous dise pas si d’ autres erreurs ).


Solutions compatibles POSIX:

Les solutions entièrement conformes à POSIX sont limitées ou nécessitent un travail supplémentaire.

Si la sortie de find doit de toute façon être capturée dans un fichier (ou supprimée), la solution basée sur le pipeline de la réponse de Jonathan Leffler est simple, robuste et compatible POSIX:

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

Notez que l’ordre des redirections est important: 2>&1 doit venir en premier .

La capture de la sortie stdout dans un fichier permet à 2>&1 d’envoyer uniquement des messages d’erreur via le pipeline, sur lesquels grep peut alors fonctionner sans ambiguïté.

Le seul inconvénient est que le code de sortie global sera la commande grep , et non la find , qui dans ce cas signifie: s’il n’y a aucune erreur ou seulement des erreurs de refus d’autorisation, le code de sortie sera 1 ( défaillance de signalisation). , sinon (erreurs autres que la permission refusée) 0 – ce qui est le contraire de l’intention.
Cela dit, le code de sortie de find est rarement utilisé de toute façon , car il transmet souvent peu d’informations au-delà d’ une défaillance fondamentale telle que le passage d’un chemin inexistant.
Cependant, le cas spécifique où seuls certains des chemins d’entrée sont inaccessibles en raison du manque d’permissions se reflète dans le code de sortie de find (à la fois dans GNU et BSD find ): si une erreur est refusée pour les fichiers traités , le code de sortie est défini sur 1 .

La variante suivante concerne ce qui suit:

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

Maintenant, le code de sortie indique si des erreurs autres que la Permission denied sont survenues: 1 si oui, 0 sinon.
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 aucune erreur ou uniquement des erreurs de refus d’autorisation sont survenues.
C’est sans doute mieux que de simplement faire passer le code de sortie de la recherche, comme dans la solution du haut.


gniourf_gniourf dans les commentaires propose une généralisation (toujours conforme à POSIX) de cette solution en utilisant des redirections sophistiquées , qui fonctionnent même avec le comportement par défaut d’impression des chemins de fichiers 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 ), afin que les messages d’erreur seuls puissent être transmis à grep via stdout.

Sans ces redirections, les données (chemins de fichiers) et les messages d’erreur seraient acheminés vers grep via stdout, et grep ne serait alors pas en mesure de distinguer le message d’erreur Permission denied et un fichier (hypothétique) .

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


Notes sur les réponses existantes:

  • Il y a plusieurs points à noter à propos de la réponse de Michael Brux , find . ! -readable -prune -o -print find . ! -readable -prune -o -print find . ! -readable -prune -o -print :

    • Il nécessite une find GNU ; notamment, cela ne fonctionnera pas sur macOS. Bien sûr, si vous avez seulement besoin de la commande pour travailler avec GNU find , cela ne vous posera aucun problème.

    • Certaines erreurs Permission denied peuvent encore apparaître: find ! -readable -prune find ! -readable -prune signale ces erreurs pour les éléments enfants des répertoires pour lesquels l’utilisateur actuel dispose de l’autorisation r , mais ne dispose pas de l’autorisation x (exécutable). La raison en est que parce que le répertoire lui même est lisible, -prune n’est pas exécuté et la tentative de descente dans ce répertoire déclenche alors les messages d’erreur. Cela dit, le cas typique est que la permission de r soit manquante.

    • Remarque: Le point suivant est une question de philosophie et / ou de cas d’utilisation spécifique, et vous pouvez décider que cela ne vous concerne pas et que la commande correspond bien à vos besoins, surtout si vous ne faites qu’imprimer les chemins:

      • Si vous conceptualisez le filtrage des messages d’erreur refusés par l’autorisation comme une tâche distincte que vous souhaitez pouvoir appliquer à une commande find , l’approche opposée de la prévention proactive des erreurs refusées par la permission nécessite d’introduire du bruit dans la commande find . introduit également la complexité et les pièges logiques.
      • Par exemple, le commentaire le plus voté de la réponse de Michael (à ce jour) tente de montrer comment étendre la commande en incluant un filtre -name , comme suit:
        find . ! -readable -prune -o -name '*.txt'
        Ceci, cependant, ne fonctionne pas comme prévu, car l’action d’ -print est requirejse (une explication peut être trouvée dans cette réponse ). De telles subtilités peuvent introduire des bogues.
  • La première solution dans la réponse de Jonathan Leffler , find . 2>/dev/null > files_and_folders find . 2>/dev/null > files_and_folders , comme il le déclare lui-même, fait taire aveuglément tous les messages d’erreur (et la solution de contournement est lourde et pas complètement robuste, comme il l’explique également). D’un sharepoint vue pragmatique , 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 la brume , sudo find . > files_and_folders sudo find . > files_and_folders , est concis et pragmatique, mais mal avisé pour autre chose que la simple impression de noms de fichiers , pour des raisons de sécurité: parce que vous êtes un utilisateur root , vous risquez de voir tout un système endommagé par find ou une version malicieuse, ou une invocation incorrecte qui écrit quelque chose de manière inattendue, ce qui ne pourrait pas arriver si vous aviez lancé ceci avec des privilèges normaux “(d’après un commentaire de la réponse de mistie sortingpleee ).

  • La 2ème solution dans la réponse de viraptor , find . 2>&1 | grep -v 'Permission denied' > some_file find . 2>&1 | grep -v 'Permission denied' > some_file 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 via le pipeline) et, éventuellement, au lieu de signaler des erreurs non autorisées par stderr, chemins de sortie dans le fichier de sortie.

Utilisation:

 find . 2>/dev/null > files_and_folders 

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

Si vous voulez vraiment garder d’autres erreurs possibles, telles qu’un trop grand nombre de sauts sur un lien symbolique, mais pas la permission refusée, vous devrez probablement deviner que vous n’avez pas beaucoup de fichiers appelés ‘permission refusée’ et essaye:

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

Si vous voulez ssortingctement filtrer uniquement 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 la suivante: 2>&1 > files_and_folders | . Le tube redirige la sortie standard vers la commande grep et est appliquée en premier. Le 2>&1 envoie une erreur standard au même endroit que la sortie standard (le tuyau). Le > files_and_folders envoie une sortie standard (mais pas une erreur standard) à un fichier. Le résultat net est que les messages écrits dans une erreur standard sont envoyés dans le canal et que la sortie normale de find est écrite dans le fichier. Le grep filtre la sortie standard (vous pouvez décider à quel point vous souhaitez qu’il soit sélectif, et vous devrez peut-être modifier l’orthographe en fonction des parameters régionaux et O / S) et le final >&2 signifie que les messages d’erreur restants aller à l’erreur standard une fois de plus. La redirection finale pourrait être considérée comme facultative sur le terminal, mais ce serait une très bonne idée de l’utiliser dans un script pour que les messages d’erreur apparaissent en cas d’erreur standard.

Il y a des variations sans fin 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é du shell Bourne (Bash, Korn,…) et toute version de find compatible avec POSIX.

Si vous souhaitez vous adapter à la version spécifique de find vous avez sur votre système, il peut y avoir des options alternatives 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.

Utilisation:

 find . ! -readable -prune -o -print 

ou plus généralement

 find  ! -readable -prune -o  -print 
  • pour éviter la “permission refusée”
  • ET NE PAS supprimer les autres messages d’erreur
  • ET obtenir le statut de sortie 0 (“tous les fichiers sont traités avec succès”)

Fonctionne avec: find (GNU findutils) 4.4.2. Contexte:

  • Le test lisible correspond aux fichiers lisibles. Le ! L’opérateur retourne true lorsque le test est faux. Et ! -readable ! -readable correspond aux répertoires (& fichiers) non lisibles.
  • L’action -prune ne descend pas dans le répertoire.
  • ! -readable -prune ! -readable -prune peut être traduit en: si le répertoire n’est pas lisible, ne le descendez pas.
  • Le test -readable prend en compte les listes de contrôle d’access et autres artefacts d’permissions que le test -perm ignore.

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

Si vous voulez lancer la recherche depuis la racine “/”, vous verrez probablement des résultats tels que:

 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 find /. -name 'toBeSearched.file' : sudo find /. -name 'toBeSearched.file' sudo find /. -name 'toBeSearched.file' . il demande le mot de passe super utilisateur, quand entrer le mot de passe, vous verrez le résultat que vous voulez vraiment.

  2. Vous pouvez utiliser la redirection de la sortie d’erreur standard depuis (généralement affichage / écran) vers certains fichiers et éviter de voir les messages d’erreur à l’écran! redirect vers un fichier spécial / dev / null:

     find /. -name 'toBeSearched.file' 2>/dev/null 
  3. Vous pouvez redirect la sortie d’erreur standard depuis (affichage / écran en général) vers la sortie standard (affichage / écran en général), puis diriger avec la commande grep avec le paramètre -v “invert” pour ne pas voir les lignes de sortie avec “autorisation refusée” paires de mots:

     find /. -name 'toBeSearched.file' 2>&1 | grep -v 'Permission denied' 

Je devais utiliser:

 find / -name expect 2>/dev/null 

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

Je m’attendais à être le lieu du programme attendu que je cherchais.

Enfoncez stderr dans /dev/null en utilisant 2> / dev / null

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

Vous pouvez également utiliser les prédicats -perm et -prune pour éviter de passer dans des répertoires illisibles (voir aussi Comment supprimer les instructions d’impression “autorisation refusée” du programme de recherche? – Unix & Linux Stack Exchange ):

 find . -type d ! -perm -g+r,u+r,o+r -prune -o -print > files_and_folders 

Rediriger l’erreur standard. Par exemple, si vous utilisez bash sur une machine Unix, vous pouvez redirect l’erreur standard vers / dev / null comme ceci:

 find . 2>/dev/null >files_and_folders 

Bien que les approches ci-dessus ne traitent pas le cas pour Mac OS X parce que Mac Os X ne prend pas en charge le commutateur -readable vous pouvez éviter les erreurs de «permission refusée» 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$ find . -type f -name "your_pattern" -exec du -ch {} + 2>/dev/null | grep total$ .

Cela retournera la taille totale des fichiers d’un motif donné. Notez le 2>/dev/null à la fin de la commande find.

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

 find . 2>/dev/null > some_file 

ou rejoignez d’abord stderr et stdout, puis lancez ces erreurs spécifiques:

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

Réponse simple:

find . > files_and_folders 2>&-

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

  • Le code de sortie sera toujours 1 si des erreurs ” Permission denied ” seraient imprimées

Réponse robuste pour GNU find :

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

Passez des options supplémentaires pour find cette option -prune (évitez de descendre), mais -print toujours tout répertoire ( -type d ) qui ne possède pas ( \! ) -executable permissions à la fois -readable et -executable , ou ( -o ) -print tout autre fichier .

  • -readable options -readable et -executable sont des extensions GNU, ne faisant pas partie du standard POSIX
  • Peut toujours renvoyer « Permission denied » sur les fichiers anormaux / corrompus (par exemple, voir le rapport de bogue affectant les systèmes de fichiers montés sur conteneur utilisant lxcfs

Une réponse robuste qui fonctionne avec tout résultat compatible avec POSIX (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 transmettre le stream d’erreur standard à grep , en supprimant toutes les lignes contenant la chaîne 'Permission denied' .

LC_ALL=C définit l’ environnement local POSIX en utilisant une variable d’environnement , 3>&2 2>&1 1>&3 et 3>&2 2>&1 descripteurs de fichiers en double pour diriger le stream d’erreur standard vers grep et [ $? = 1 ] [ $? = 1 ] utilise [] pour inverser le code d’erreur renvoyé par grep pour se rapprocher du comportement d’origine de find .

  • Filtrera également 'Permission denied' erreurs 'Permission denied' dues à la redirection de sortie (par exemple, si le fichier files_and_folders n’est pas accessible en écriture)

Pour éviter les avertissements de permission refusée, indiquez find pour ignorer les fichiers illisibles en les supprimant de la recherche. Ajouter une expression en tant que OU à votre recherche, par exemple

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

Cela dit surtout (correspond à un fichier illisible et le taille de la liste) OU (correspond à un nom comme * .jbd et affiche-le [avec ls]) . (Rappelez-vous que par défaut les expressions sont AND ensemble sauf si vous utilisez -or.) Vous avez besoin des -ls dans la deuxième expression ou find peut append une action par défaut pour afficher l’une ou l’autre des correspondances. .

Mais si vous recherchez de vrais fichiers sur votre système, il n’y a généralement aucune raison de chercher dans / dev, qui contient beaucoup de fichiers, vous devez donc append une expression qui exclut ce répertoire, comme par exemple:

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

Donc (correspondance avec le fichier illisible et élagage de la liste) OU (chemin de correspondance / dev et prune de la liste) OU (correspondance du fichier comme * .jbd et affichage) .

utilisation

 sudo find / -name file.txt 

C’est stupide (parce que vous élevez la recherche) et non sécurisé, mais beaucoup plus court pour écrire.

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 ne gère correctement le code retour / code de sortie du processus. J’utilise la commande find dans les scripts bash pour localiser certains répertoires, puis inspecter leur contenu. J’évalue la commande trouver le succès en utilisant le code de sortie: une valeur zéro fonctionne, sinon échoue.

La réponse fournie ci-dessus par Michael Brux fonctionne parfois. Mais j’ai un scénario dans lequel il échoue! J’ai découvert le problème et l’ai corrigé moi-même. Je dois tailler les fichiers lorsque:

 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 est la suivante:

 -type d ! -readable ! -executable -prune 

Cela ne fonctionne pas toujours. Cela signifie qu’une élagage est déclenché lorsqu’une correspondance est:

 it is directory AND no read access AND no execute access 

Cette séquence d’expressions échoue lorsque l’access en lecture est accordé mais qu’aucun access d’exécution n’est disponible.

Après quelques tests, j’ai réalisé à ce sujet et changé ma solution de script shell pour:

nice find / home * / -maxdepth 5 -suivre \
\ (-type d -a ! \ (-readable -a -executable \) \) -prune \
-o \
\ (-type d -a -readable -a -executable -a -name “$ {m_find_name}” \) -print

La clé ici est de placer le “pas vrai” pour une expression combinée:

 has read access AND has execute access 

Sinon, l’access n’est pas complet, ce qui signifie: élaguer. Cela s’est avéré efficace pour moi dans un scénario où les solutions proposées précédemment avaient échoué.

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

  • Pourquoi utiliser commande gentille? J’ai eu l’idée ici . Au départ, j’ai pensé qu’il serait intéressant de réduire la priorité des processus lors de la recherche d’un système de fichiers complet. 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 * /? Ceci n’est pas pertinent pour ce sujet. J’installe toutes les applications à la main via la compilation du code source avec des utilisateurs non privilégiés (pas root). Ils sont installés dans “/ home”. Je peux avoir plusieurs binarys et versions vivant ensemble. Je dois localiser tous les répertoires, inspecter et sauvegarder en mode maître-esclave. Je peux avoir plusieurs “/ home” (plusieurs disques fonctionnant sur un serveur dédié).
  • ¿Pourquoi utiliser -follow? Les utilisateurs peuvent créer des liens symboliques vers des répertoires. Son utilité dépend, je dois garder une trace des chemins absolus trouvés.

Vous pouvez utiliser la fonction invert-match grep -v

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

comme ça:

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

Devrait à la magie

– = pour MacOS = –

Créez une nouvelle commande en utilisant un alias: ajoutez simplement la ligne ~ / .bash_profile:

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

et dans la nouvelle fenêtre Terminal, vous pouvez l’appeler:

 $ file=; search 

par exemple:

$ file = etc; chercher

Si vous utilisez CSH ou TCSH, voici une solution:

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

Si vous voulez une sortie vers le terminal:

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

Cependant, comme le décrit la FAQ “csh-whynot”, vous ne devez pas utiliser CSH.

Vous avez également une solution simple pour mettre vos résultats de recherche dans un fichier.

trouver . -name ‘NameOfSearchedFile’ >> results.txt