Remarque:
* Cette réponse va probablement plus loin que le cas d'utilisation ne le justifie et find 2>/dev/nullpeut être suffisante dans de nombreuses situations. Il peut encore être intéressant pour une perspective multiplateforme et pour sa discussion de certaines techniques avancées de shell dans l'intérêt de trouver une solution aussi robuste que possible, même si les cas protégés peuvent être largement hypothétiques.
* Si votre système est configuré pour afficher des messages d'erreur localisés , préfixez les findappels ci-dessous avec LC_ALL=C( LC_ALL=C find ...) pour vous assurer que les messages en anglais sont signalés, afin que cela grep -v 'Permission denied'fonctionne comme prévu. Invariablement, cependant, les messages d'erreur qui ne sera pas affiché seront alors en anglais.
Si votre shell est bashouzsh , il existe une solution qui est robuste tout en étant relativement simple , en utilisant uniquement des findfonctionnalités compatibles POSIX ; bien que bashlui-même ne fasse pas partie de POSIX, la plupart des plates-formes Unix modernes viennent avec, ce qui rend cette solution largement portable:
find . > files_and_folders 2> >(grep -v 'Permission denied' >&2)
Remarque: Il y a une petite chance qu'une partie de grepla sortie arrive après la find fin, car la commande globale n'attend pas la fin de la commande à l'intérieur >(...). Dans bash, vous pouvez empêcher cela en ajoutant | catà la commande.
>(...)est une substitution de processus de sortie (rarement utilisée) qui permet de rediriger la sortie (dans ce cas, stderr output ( ) vers le stdin de la commande à l'intérieur .
En plus de et , les prend également en charge en principe , mais en essayant de les combiner avec la redirection à partir de stderr , comme cela se fait ici ( ), semble être ignoré silencieusement (in ).2>>(...)
bashzshksh2> >(...)ksh 93u+
grep -v 'Permission denied'filtres à ( -v) toutes les lignes (de la findcommande de flux stderr) qui contiennent l'expression Permission deniedet les sorties les lignes restantes à stderr ( >&2).
Cette approche est:
robuste : grepn'est appliqué qu'aux messages d'erreur (et non à une combinaison de chemins de fichiers et de messages d'erreur, pouvant conduire à des faux positifs), et des messages d'erreur autres que ceux refusés sont transmis à stderr.
sans effet secondaire : findle code de sortie de est conservé: l'incapacité d'accéder à au moins un des éléments du système de fichiers rencontrés entraîne un code de sortie 1(bien que cela ne vous indique pas si des erreurs autres que celles refusées se sont produites (aussi)).
Solutions conformes POSIX:
Les solutions entièrement conformes à POSIX ont des limites ou nécessitent un travail supplémentaire.
Si findla sortie « doit être capturé dans un fichier de toute façon (ou supprimé au total), alors la solution pipeline de la 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 est important: 2>&1doit venir en premier .
Capturer la sortie stdout dans un fichier à l'avance permet 2>&1d'envoyer uniquement des messages d'erreur via le pipeline, qui greppeut ensuite fonctionner sans ambiguïté.
Le seul inconvénient est que le code de sortie global sera celui de la grepcommande , pas celui find, ce qui signifie dans ce cas: s'il n'y a aucune erreur ou seulement des erreurs refusées, le code de sortie sera 1( échec de la signalisation ), sinon ( erreurs autres que celles refusées) 0- ce qui est le contraire de l'intention.
Cela dit, findle code de sortie de '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 de même que quelques - unsdes chemins d'entrée inaccessibles en raison du manque d'autorisations se reflète dans findle code de sortie de (à la fois dans GNU et BSD find): si une erreur de refus d'autorisations se produit pour l' un des fichiers traités, le code de sortie est défini sur 1.
La variation suivante répond à 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 celles qui se Permission denied sont produites: 1si oui, 0sinon.
En d'autres termes: le code de sortie reflète désormais la véritable intention de la commande: success ( 0) est signalé, si aucune erreur ou seulement des erreurs d'autorisation refusée se sont produites.
C'est sans doute encore mieux que de simplement passer findle code de sortie de, comme dans la solution en haut.
gniourf_gniourf dans les commentaires propose une généralisation (toujours conforme POSIX) de cette solution en utilisant des redirections sophistiquées , qui fonctionne même avec le comportement par défaut d'imprimer les chemins d'accès aux 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é 3est utilisé pour permuter temporairement stdout ( 1) et stderr ( 2), de sorte que les messages d'erreur seuls puissent être dirigés grepvia stdout.
Sans ces redirections, les données (chemins de fichiers) et les messages d'erreur seraient acheminés grepvia stdout et grepne seraient alors pas en mesure de faire la distinction entre le message d'erreur Permission denied et un fichier (hypothétique) dont le nom contient la phrase Permission denied.
Comme dans la première solution, cependant, le code de sortie signalé sera grep«s», find« non », mais la même correction que ci-dessus peut être appliquée.
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:
Cela nécessite GNU find ; notamment, cela ne fonctionnera pas sur macOS. Bien sûr, si vous n'avez besoin que de la commande pour travailler avec GNU find, ce ne sera pas un problème pour vous.
Certaines Permission deniederreurs peuvent encore apparaître: find ! -readable -prunesignale de telles erreurs pour les éléments enfants des répertoires pour lesquels l'utilisateur actuel a l' rautorisation, mais n'a pas l' xautorisation (exécutable). La raison en est que parce que le répertoire lui - même est lisible, -prunen'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 que l' rautorisation soit manquante.
Remarque: 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 correspond bien à vos besoins, surtout si vous n'avez qu'à imprimer les chemins:
- Si vous conceptualisez le filtrage des messages d'erreur d'autorisation refusée comme une tâche distincte que vous souhaitez pouvoir appliquer à n'importe quelle
find commande, alors l'approche opposée de la prévention proactive des erreurs d'autorisation refusée nécessite l'introduction de «bruit» dans la findcommande, qui introduit également complexité et pièges logiques .
- Par exemple, le commentaire le plus voté sur la réponse de Michael (au moment d'écrire ces lignes) tente de montrer comment étendre la commande en incluant un
-namefiltre, comme suit:
find . ! -readable -prune -o -name '*.txt'
Cela, cependant, ne fonctionne pas comme prévu, car l' -printaction de fin est requise (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_folderscomme il dit lui-même, réduit au silence aveuglément tous les messages d'erreur (et la solution de contournement est lourd et pas complètement robuste, comme il l' explique aussi). Pragmatiquement parlant , cependant, c'est la solution la plus simple , car vous pouvez vous contenter de supposer que toutes les erreurs seraient liées aux autorisations.
La réponse de brouillard , sudo find . > files_and_folders, est concise et pragmatique, mais mal avisé pour autre chose que simplement l' impression des noms de fichiers , pour des raisons de sécurité: parce que vous êtes en cours d' exécution en tant que root utilisateur « , vous risquez d' avoir votre système tout étant sali par un bogue dans trouvaille 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 exécutiez cela avec des privilèges normaux "(d'après un commentaire sur la réponse de mist par tripleee ).
La 2e solution dans la réponse de viraptor , find . 2>&1 | grep -v 'Permission denied' > some_filecourt le risque de faux positifs (en raison de l'envoi d'un mélange de stdout et stderr via le pipeline), et, potentiellement, au lieu de signaler des erreurs non refusées par stderr, les capture le long des chemins de sortie dans le fichier de sortie.
find . 2>&1 > files_and_folders | grep -v 'Permission denied' >&2:?