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
:?{ find . 3>&2 2>&1 1>&3 | grep -v 'Permission denied' >&3; } 3>&2 2>&1
>(...)
sont spécifiques à Bash.find
doit être soulignée et annoncée:find
le code de sortie de est notoirement inutile. Ici, il est très probable que ce sera différent de zéro (et inutilement).execute/search
autorisation en mode fichier afin de «rechercher» un répertoire (récupérer les inodes des fichiers contenus).find
le fait pour descendre dans un sous-répertoire (en plus d'exiger l'read
autorisation de lister les fichiers dans un répertoire). Ce n'est pas un «bug» ou une «erreur de portage».Utilisation:
Cela ne masque pas seulement les
Permission denied
erreurs, 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 les autorisations refusées, alors vous devrez probablement deviner que vous n'avez pas beaucoup de fichiers appelés 'autorisation refusée' et essaye:
Si vous souhaitez filtrer uniquement l'erreur standard, vous pouvez utiliser la construction plus élaborée:
La redirection d' E / S sur la
find
commande est:2>&1 > files_and_folders |
. Le canal redirige la sortie standard vers lagrep
commande et est appliqué en premier. L'2>&1
envoie l'erreur standard au même endroit que la sortie standard (le tuyau). L'> files_and_folders
envoie la sortie standard (mais pas d' erreur standard) dans un fichier. Le résultat net est que les messages écrits sur l'erreur standard sont envoyés dans le canal et que la sortie régulière defind
est écrite dans le fichier. Lesgrep
filtres filtrent la sortie standard (vous pouvez décider du niveau de sélectivité souhaité, et vous devrez peut-être modifier l'orthographe en fonction des paramètres régionaux et des O / S) et la finale>&2
signifie que les messages d'erreur survivants (écrits sur la sortie standard) retournent à l'erreur standard. La redirection finale pourrait être considérée comme facultative au niveau du terminal, mais ce serait une très bonne idée de l'utiliser dans un script afin que les messages d'erreur apparaissent sur l'erreur standard.Il existe 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é du shell Bourne (Bash, Korn,…) et toute version compatible POSIX de
find
.Si vous souhaitez vous adapter à la version spécifique que
find
vous avez sur votre système, d'autres options peuvent être disponibles. GNUfind
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.la source
2>/dev/null
, sans espace!2>
est une seule unité sans aucun espace; vous pouvez avoir un espace entre celui-ci et le nom du fichier. De même avec d'autres redirections, telles que2>&1
(qui redirige l'erreur standard au même endroit que la sortie standard va), ou2>&-
qui ferme l'erreur standard, etc. Voir Redirection pour les détails sanglants restants. (Le code ci-dessus est un shell générique de type POSIX, non spécifique àbash
.)Utilisation:
ou plus généralement
Fonctionne avec: find (GNU findutils) 4.4.2. Contexte:
-readable
test correspond aux fichiers lisibles. L'!
opérateur renvoie true, lorsque test est faux. Et! -readable
correspond aux répertoires non lisibles (& fichiers).-prune
action ne descend pas dans le répertoire.! -readable -prune
peut être traduit en: si le répertoire n'est pas lisible, n'y descendez pas.-readable
test prend en compte les listes de contrôle d'accès et autres artefacts d'autorisations que le-perm
test ignore.Voir aussi
find
(1) la page de manuel pour plus de détails.la source
-o
:find . ! -readable -prune -o -name '*.txt'
find
ne comprend pas-readable
en option; nifind
pour BSD et donc Mac OS X (je ne suis pas sûr des autres systèmes). Donc, là où GNU estfind
garanti, cela fonctionne très bien, mais il n'est pas évident de l'adapter si vous ne pouvez pas garantir que GNU estfind
installé sur le système . (Cela fonctionnera bien sous Linux; cela peut ou peut ne pas fonctionner ailleurs.)find . ! -readable -prune -o -name '*.txt'
ne semblent pas fonctionner sur Ubuntu 14.04 en utilisant find 4.2.2. Il semble ingérer le-name
. Pour une raison étrange, j'ai du succès avecfind . \( ! -readable -prune \) -o -name '*.txt' -print
Si vous souhaitez démarrer la recherche à partir de la racine "/", vous verrez probablement des résultats tels que:
C'est à cause de la permission. Pour résoudre ceci:
Vous pouvez utiliser la commande sudo:
Il demande le mot de passe du super utilisateur, lorsque vous entrez le mot de passe, vous verrez le résultat que vous voulez vraiment. Si vous n'êtes pas autorisé à utiliser la commande sudo, ce qui signifie que vous n'avez pas le mot de passe de super utilisateur, demandez d'abord à l'administrateur système de vous ajouter au fichier sudoers.
Vous pouvez utiliser rediriger la sortie d'erreur standard de (généralement affichage / écran) vers un fichier et éviter de voir les messages d'erreur à l'écran! rediriger vers un fichier spécial / dev / null:
Vous pouvez utiliser rediriger la sortie d'erreur standard de (généralement affichage / écran) vers la sortie standard (généralement afficher / écran), puis rediriger avec la commande grep avec le paramètre -v "inverser" pour ne pas voir les lignes de sortie qui ont "Autorisation refusée" paires de mots:
la source
sudo find...
J'ai dû utiliser:
en spécifiant le nom de ce que je voulais trouver, puis en lui disant de rediriger toutes les erreurs vers / dev / null
Attendez-vous à être l'emplacement du programme Attendre que je cherchais.
la source
expect
. Au lieu de cela, ilexpect
s'agit simplement du nom du fichier que cette commande essaiera de trouver.Tuyau
stderr
vers/dev/null
en utilisant 2> / dev / nullfind . -name '...' 2>/dev/null
la source
find . -name '...' -print 2>/dev/null
Vous pouvez également utiliser les prédicats
-perm
et-prune
pour éviter de descendre dans des répertoires illisibles (voir aussi Comment supprimer les instructions d'impression "autorisation refusée" du programme find? - Unix & Linux Stack Exchange ):la source
-perm -g+r,u+r,o+r
correspond simplement aux fichiers dont l'r
autorisation (lecture) est définie pour les 3 entités de sécurité du fichier , ce qui n'a aucune relation directe avec le fait que l' utilisateur actuel puisse ou non lire ce fichier. Il a le potentiel de manquer des fichiers que l'utilisateur actuel peut lire et de faire correspondre des fichiers qu'ils ne peuvent pas.find . -type d ! \( -perm -u+r -o -perm -g+r -o -perm -o+r \) -prune -o -print
serait la bonne solution.-readable
avec-perm
- voir mon commentaire précédent et considérons cet exemple:echo 'hi' > file; sudo chown nobody:nobody file; sudo chmod o-r file; find file -perm -u=r
imprimefile
, car son bit de lecture utilisateur est défini, mais il concerne l'nobody
utilisateur, pas l'utilisateur actuel. L'utilisateur actuel ne peut pas lire ce fichier; essayezcat file
. Voir aussi: ma réponse .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:
la source
Bien que les approches ci-dessus ne résolvent pas le cas de Mac OS X, car Mac Os X ne prend pas en charge le
-readable
commutateur, c'est ainsi que vous pouvez éviter les erreurs «Autorisation 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 d'un certain modèle dans un répertoire,2>/dev/null
cela fonctionnera toujours comme indiqué ci-dessous.find . -type f -name "your_pattern" -exec du -ch {} + 2>/dev/null | grep total$
.Cela renverra la taille totale des fichiers d'un modèle donné. Notez la
2>/dev/null
fin de la commande find.la source
2>/dev/null
. Pouvez-vous expliquer la partie-exec du -ch {} + 2>/dev/null | grep total$
.-exec
option pour prendre d'autres mesures sur les fichiers ou répertoires trouvés par lafind
commande.du -ch file_pattern
calcule la taille de chaque fichier correspondantfile_pattern
et la dernière ligne de cette sortie est le total général de tous les fichiers qui correspondent à lafile_pattern
. Voir la page de manuel pourdu
.grep total
filtre simplement la ligne qui extrait le grand total (qui est la dernière ligne).Ces erreurs sont imprimées sur la sortie d'erreur standard (fd 2). Pour les filtrer, redirigez simplement toutes les erreurs vers / dev / null:
ou rejoignez d'abord stderr et stdout, puis relevez ces erreurs spécifiques:
la source
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.1
siPermission denied
des erreurs ' ' seraient autrement impriméesRéponse robuste pour GNU
find
:find . -type d \! \( -readable -executable \) -prune -print -o -print > files_and_folders
Passez des options supplémentaires à
find
cela-prune
(empêchez de descendre dans) mais toujours-print
tout répertoire ( ) qui ne possède pas ( ) les deux autorisations et , ou ( ) tout autre fichier.-type
d
\!
-readable
-executable
-o
-print
-readable
et les-executable
options sont des extensions GNU, ne font pas partie de la norme POSIXPermission denied
' sur des fichiers anormaux / corrompus (par exemple, voir le rapport de bogue affectant les systèmes de fichiers montés sur les conteneurs à l'aide delxcfs
<v2.0.5)Réponse robuste qui fonctionne avec tout 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 transmettre le flux d'erreur standard à
grep
, en supprimant toutes les lignes contenant la'Permission denied'
chaîne.LC_ALL=C
définit les paramètres régionaux POSIX à l' aide d'une variable d'environnement ,3>&2 2>&1 1>&3
et3>&2 2>&1
des descripteurs de fichiers en double pour diriger le flux d'erreur standard versgrep
, et[ $? = 1 ]
utilise[]
pour inverser le code d'erreur renvoyé pargrep
pour approximer le comportement d'origine defind
.'Permission denied'
erreurs dues à la redirection de sortie (par exemple, si lefiles_and_folders
fichier lui-même n'est pas accessible en écriture)la source
-perm
solution basée sur la valeur ne vaut pas la peine d'être présentée, car plus fondamentalement que ne le suggère la citation fait quelque chose de différent que prévu: c'est un test purement centré sur le fichier , relatif au propriétaire du fichier et groupe, aucun des deux n'ayant une relation garantie avec l'utilisateur appelant la commande (voir ma réponse . Il semble que votre solution GNU révisée neecho 'hi' > file; sudo chown nobody:nobody file; sudo chmod o-r file; find file -perm -u=r
imprimefile
, car son bit de lecture utilisateur est défini, mais il se rapporte à l'nobody
utilisateur , pas l'utilisateur actuel. L'utilisateur actuel ne peut pas lire ce fichier; essayezcat file
.-perm
cela ne fonctionne pas pour déterminer les autorisations actuelles de l'utilisateur. Suppression de cette alternative de cette réponse.Pour éviter uniquement les avertissements d'autorisation refusée, dites à find d'ignorer les fichiers illisibles en les élaguant de la recherche. Ajoutez une expression sous forme de OU à votre recherche, telle que
Cela dit principalement (faire correspondre un fichier illisible et l'élaguer de la liste) OU (faire correspondre un nom comme * .jbd et l'afficher [avec ls]) . (N'oubliez pas que par défaut, les expressions sont ET ensemble sauf si vous utilisez -or.) Vous avez besoin des -ls dans la deuxième expression, sinon find peut ajouter une action par défaut pour afficher l'une ou l'autre correspondance, qui vous montrera également tous les fichiers illisibles .
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 ajouter une expression qui exclut ce répertoire, comme:
Donc (faire correspondre le fichier illisible et tailler à partir de la liste) OU (faire correspondre chemin / dev et tailler à partir de la liste) faites OU ( faites correspondre le fichier comme * .jbd et affichez-le) .
la source
utilisation
C'est stupide (parce que vous élevez la recherche) et non sécurisé, mais beaucoup plus court à écrire.
la source
sudo
. Vous risquez d'avoir tout votre système endommagé par un boguefind
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 l'exécutiez avec des privilèges normaux.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 le succès de la commande 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 résolu moi-même. J'ai besoin d'élaguer des fichiers lorsque:
Voir le problème clé ici est: ET / OU. Une bonne séquence de condition suggérée que je lis est:
Cela ne fonctionne pas toujours. Cela signifie qu'un pruneau est déclenché lorsqu'une correspondance est:
Cette séquence d'expressions échoue lorsque l'accès en lecture est accordé mais aucun accès d'exécution ne l'est.
Après quelques tests, je m'en suis rendu compte et j'ai changé ma solution de script shell en:
La clé ici est de placer le «pas vrai» pour une expression combinée:
Sinon, il n'a pas un accès complet, ce qui signifie: taillez-le. Cela s'est avéré efficace 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.
la source
nice
etfind $HOME -maxdepth 5 -follow ...
?${m_find_name}
), et contient plusieurs options non pertinentes à la question (nice
,/home*
,-maxdepth 5
,-follow
). J'ai ajouté une réponse qui résout le problème spécifique du «filtrage des répertoires lisibles mais non exécutables» de manière plus concise, tout en restant polyvalent.Vous pouvez utiliser la correspondance inversée grep -v
comme ça:
Devrait à la magie
la source
- = Pour MacOS = -
Créez une nouvelle commande en utilisant l'alias: ajoutez simplement la ligne ~ / .bash_profile:
et dans une nouvelle fenêtre de terminal, vous pouvez l'appeler:
la source
Si vous utilisez CSH ou TCSH, voici une solution:
Si vous souhaitez une sortie vers le terminal:
Cependant, comme le décrit la FAQ "csh-whynot", vous ne devez pas utiliser CSH.
la source