Remarque:
* Cette réponse va probablement plus loin que le cas d'utilisation ne le justifie et find 2>/dev/null
peut ê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 find
appels 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 bash
ouzsh
, il existe une solution qui est robuste tout en étant relativement simple , en utilisant uniquement des find
fonctionnalités compatibles POSIX ; bien que bash
lui-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 grep
la 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>
>(...)
bash
zsh
ksh
2> >(...)
ksh 93u+
grep -v 'Permission denied'
filtres à ( -v
) toutes les lignes (de la find
commande de flux stderr) qui contiennent l'expression Permission denied
et les sorties les lignes restantes à stderr ( >&2
).
Cette approche est:
robuste : grep
n'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 : find
le 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 find
la 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>&1
doit venir en premier .
Capturer la sortie stdout dans un fichier à l'avance permet 2>&1
d'envoyer uniquement des messages d'erreur via le pipeline, qui grep
peut ensuite fonctionner sans ambiguïté.
Le seul inconvénient est que le code de sortie global sera celui de la grep
commande , 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, find
le 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 find
le 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: 1
si oui, 0
sinon.
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 find
le 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é 3
est utilisé pour permuter temporairement stdout ( 1
) et stderr ( 2
), de sorte que les messages d'erreur seuls puissent être dirigés grep
via stdout.
Sans ces redirections, les données (chemins de fichiers) et les messages d'erreur seraient acheminés grep
via stdout et grep
ne 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 denied
erreurs peuvent encore apparaître: find ! -readable -prune
signale de telles erreurs pour les éléments enfants des répertoires pour lesquels l'utilisateur actuel a l' r
autorisation, mais n'a pas l' x
autorisation (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 descendre dans ce répertoire déclenche alors les messages d'erreur. Cela dit, le cas typique est que l' r
autorisation 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 find
commande, 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
-name
filtre, comme suit:
find . ! -readable -prune -o -name '*.txt'
Cela, cependant, ne fonctionne pas comme prévu, car l' -print
action 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_folders
comme 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_file
court 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
:?