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

795

Je dois masquer tous les messages de refus d' accès de:

find . > files_and_folders

J'expérimente quand un tel message apparaît. J'ai besoin de rassembler tous les dossiers et fichiers auxquels il ne se pose pas.

Est-il possible de diriger les niveaux d'autorisation vers le files_and_foldersfichier?

Comment masquer les erreurs en même temps?

Léo Léopold Hertz 준영
la source

Réponses:

259

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.

mklement0
la source
4
Juste une question rapide: pourquoi utilisez-vous une substitution de processus et pas seulement un tuyau find . 2>&1 > files_and_folders | grep -v 'Permission denied' >&2:?
gniourf_gniourf
2
@ LéoLéopoldHertz 준영: Si vous ne voulez pas sortir vers un fichier externe, faites simplement plus de plomberie:{ find . 3>&2 2>&1 1>&3 | grep -v 'Permission denied' >&3; } 3>&2 2>&1
gniourf_gniourf
2
@ LéoLéopoldHertz 준영: Juste que c'est compatible POSIX. Les substitutions de processus >(...)sont spécifiques à Bash.
gniourf_gniourf
2
Je ne suis pas sûr que la préservation du code de sortie de finddoit être soulignée et annoncée: findle code de sortie de est notoirement inutile. Ici, il est très probable que ce sera différent de zéro (et inutilement).
gniourf_gniourf
3
POSIX requiert explicitement l' execute/searchautorisation en mode fichier afin de «rechercher» un répertoire (récupérer les inodes des fichiers contenus). findle fait pour descendre dans un sous-répertoire (en plus d'exiger l' readautorisation de lister les fichiers dans un répertoire). Ce n'est pas un «bug» ou une «erreur de portage».
wjordan
542

Utilisation:

find . 2>/dev/null > files_and_folders

Cela ne masque pas seulement les Permission deniederreurs, 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:

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

Si vous souhaitez 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 findcommande est: 2>&1 > files_and_folders |. Le canal redirige la sortie standard vers la grepcommande et est appliqué en premier. L' 2>&1envoie l'erreur standard au même endroit que la sortie standard (le tuyau). L' > files_and_foldersenvoie 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 de findest écrite dans le fichier. Les grepfiltres 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>&2signifie 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 findvous avez sur votre système, d'autres options peuvent être disponibles. GNU finden 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.

Jonathan Leffler
la source
9
Si vous êtes comme moi, notez que le manque d'espace est important! 2>/dev/null, sans espace!
Nik
20
Le 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 que 2>&1(qui redirige l'erreur standard au même endroit que la sortie standard va), ou 2>&-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.)
Jonathan Leffler
3
J'ai dû utiliser un P majuscule parce que c'est ce que mon terminal produirait: trouver. 2> & 1 | grep -v 'Autorisation refusée'
David Doria
4
En quoi est-ce une solution acceptable? 1) Vous redirigez TOUTES les erreurs vers dev / null 2) Vous filtrez une chaîne d'erreur explicite !! En fonction de ceux-ci, il est réputé fragile et que se passe-t-il si votre fichier se trouve dans un répertoire nommé «autorisation refusée»? Oops!
Gunchars
10
Je m'oppose à la réception des chaînes d'erreur pour modifier la sortie du programme. Cela fonctionnera la plupart du temps, mais simple n'est pas la bonne solution (trouvez avec les perms ci-dessous). Pour vous donner un exemple, cela ne fonctionnera pas sur OSX car l'erreur est "Autorisation refusée". Même chose pour tout autre système où il y a même de minuscules différences dans la chaîne d'erreur (internationalisation n'importe qui?)
Gunchars
286

Utilisation:

find . ! -readable -prune -o -print

ou plus généralement

find <paths> ! -readable -prune -o <other conditions like -name> -print
  • pour éviter "Autorisation refusée"
  • ET ne supprimez PAS les (autres) messages d'erreur
  • ET obtenir l'état de sortie 0 ("tous les fichiers ont été traités avec succès")

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

  • Le -readabletest correspond aux fichiers lisibles. L' !opérateur renvoie true, lorsque test est faux. Et ! -readablecorrespond aux répertoires non lisibles (& fichiers).
  • L' -pruneaction 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.
  • Le -readabletest prend en compte les listes de contrôle d'accès et autres artefacts d'autorisations que le -permtest ignore.

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

Michael Brux
la source
6
les différences sont déjà mentionnées. si vous ne comprenez pas, alors les réponses ne font peut-être aucune différence pour vous? STDOUT est le même - STDERR est différent (vous obtenez les autres messages d'erreur avec cette réponse) - $? est différent (est 0 "réussi" avec cette réponse, quand aucune autre erreur ne se produit - est toujours> 0 "pas réussi" lors de la redirection vers dev / null) - peut-être que quelqu'un a besoin de "correct" $? dans un script
Michael Brux
6
@Masi le défaut le plus évident est la réponse de Jonathan (grep -v) exclura le nom de fichier qui contient 'Permission refusée' :)
Fruit
65
Je pense qu'il convient d'ajouter ici que si vous avez besoin d'ajouter d'autres critères de recherche, cela devrait être fait avec -o:find . ! -readable -prune -o -name '*.txt'
tempestadept
22
Notez que POSIX findne comprend pas -readableen option; ni findpour BSD et donc Mac OS X (je ne suis pas sûr des autres systèmes). Donc, là où GNU est findgaranti, cela fonctionne très bien, mais il n'est pas évident de l'adapter si vous ne pouvez pas garantir que GNU est findinstallé sur le système . (Cela fonctionnera bien sous Linux; cela peut ou peut ne pas fonctionner ailleurs.)
Jonathan Leffler
6
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
con-f-use
110

Si vous souhaitez démarrer la recherche à partir de 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 ceci:

  1. Vous pouvez utiliser la commande sudo:

    sudo find /. -name 'toBeSearched.file'

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.

  1. 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:

    find /. -name 'toBeSearched.file' 2>/dev/null
  2. 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:

    find /. -name 'toBeSearched.file' 2>&1 | grep -v 'Permission denied'
Fatih Aksu
la source
7
@scottmrogowski sauf qu'il ne répond pas à la question ... 1. demandez à l'administrateur système de vous ajouter au fichier sudoers. 2.sudo find...
Stephen
1
exactement ce que je cherchais!
DankMasterDan
92

J'ai dû utiliser:

find / -name expect 2>/dev/null

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.

Jeremy
la source
3
@Masi, la commande de la réponse n'utilise pas expect. Au lieu de cela, il expects'agit simplement du nom du fichier que cette commande essaiera de trouver.
Dhruv Kapoor
2
Rediriger aveuglément toutes les sorties de stderr juste pour ignorer une seule classe de messages d'erreur est généralement une mauvaise idée - vous perdrez toutes les autres erreurs arbitraires dans le processus.
Josip Rodin
59

Tuyau stderrvers /dev/nullen utilisant 2> / dev / null

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

Mat
la source
2
Cela fonctionne bien pour moi, même sur Mac OSX. Ou mêmefind . -name '...' -print 2>/dev/null
shadowsheep
30

Vous pouvez également utiliser les prédicats -permet -prunepour é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 ):

find . -type d ! -perm -g+r,u+r,o+r -prune -o -print > files_and_folders
sdaau
la source
4
-perm -g+r,u+r,o+rcorrespond simplement aux fichiers dont l' rautorisation (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.
mklement0
Je pense que ce find . -type d ! \( -perm -u+r -o -perm -g+r -o -perm -o+r \) -prune -o -printserait la bonne solution.
Mattia72
2
@ Mattia72: Non, il est fondamentalement impossible d'émuler complètement -readableavec -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=rimprime file, car son bit de lecture utilisateur est défini, mais il concerne l' nobodyutilisateur, pas l'utilisateur actuel. L'utilisateur actuel ne peut pas lire ce fichier; essayez cat file. Voir aussi: ma réponse .
mklement0
23

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
Jason Coco
la source
20

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 -readablecommutateur, 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/nullcela 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/nullfin de la commande find.

Bunti
la source
Belle liaison à l'OS X! La réponse de Jonathan explique la partie 2>/dev/null. Pouvez-vous expliquer la partie -exec du -ch {} + 2>/dev/null | grep total$.
Léo Léopold Hertz
1
@Masi Vous pouvez utiliser n'importe quelle commande avec -execoption pour prendre d'autres mesures sur les fichiers ou répertoires trouvés par la findcommande. du -ch file_patterncalcule la taille de chaque fichier correspondant file_patternet 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 pour du. grep totalfiltre simplement la ligne qui extrait le grand total (qui est la dernière ligne).
Bunti
13

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 relevez ces erreurs spécifiques:

find . 2>&1 | grep -v 'Permission denied' > some_file
viraptor
la source
11

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 1si Permission denieddes erreurs ' ' seraient autrement 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 à findcela -prune(empêchez de descendre dans) mais toujours -printtout répertoire ( ) qui ne possède pas ( ) les deux autorisations et , ou ( ) tout autre fichier.-typed\!-readable-executable-o-print

  • -readableet les -executableoptions sont des extensions GNU, ne font pas partie de la norme POSIX
  • Peut toujours renvoyer ' Permission 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 de lxcfs<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=Cdéfinit les paramètres régionaux POSIX à l' aide d'une variable d'environnement , 3>&2 2>&1 1>&3et 3>&2 2>&1 des descripteurs de fichiers en double pour diriger le flux d'erreur standard vers grep, et [ $? = 1 ]utilise []pour inverser le code d'erreur renvoyé par greppour approximer le comportement d'origine de find.

  • Filtre également les 'Permission denied'erreurs dues à la redirection de sortie (par exemple, si le files_and_foldersfichier lui-même n'est pas accessible en écriture)
wjordan
la source
Que pensez-vous de la proposition de réponse de JordiFerran? - - Pouvez-vous y comparer votre réponse?
Léo Léopold Hertz 준영
2
Le script shell de cette réponse, comme indiqué, n'est pas à usage général (ne répertorie que les répertoires correspondant à $ {m_find_name}) et contient plusieurs options non pertinentes pour la question (nice, / home *, -maxdepth 5, -follow). Cette réponse répond au problème spécifique du «filtrage des répertoires lisibles mais non exécutables» de manière plus concise, tout en restant polyvalent.
wjordan
1
@wjordan: Merci. J'ai supprimé mes commentaires, mais un point s'applique toujours: la -permsolution 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 ne
détecte plus les
Je ne reconnais pas la syntaxe que vous utilisez (ni comme GNU ni comme BSD), mais permettez-moi d'illustrer mon propos avec un exemple autonome: echo 'hi' > file; sudo chown nobody:nobody file; sudo chmod o-r file; find file -perm -u=rimprime file, car son bit de lecture utilisateur est défini, mais il se rapporte à l' nobodyutilisateur , pas l'utilisateur actuel. L'utilisateur actuel ne peut pas lire ce fichier; essayez cat file.
mklement0
1
@ mklement0 merci pour la discussion, j'ai réussi à produire le comportement que vous avez décrit dans un autre test (je ne sais pas ce que j'ai fait de mal la première fois), il semble que -permcela ne fonctionne pas pour déterminer les autorisations actuelles de l'utilisateur. Suppression de cette alternative de cette réponse.
wjordan
4

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

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

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:

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

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) .

simpleuser
la source
4

utilisation

sudo find / -name file.txt

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

brouillard
la source
Vous recherchez ici tout le système de fichiers, vous entendez par là "élever la recherche". Pourquoi appelez-vous cela non sécurisé? Parce qu'il recherche un système de fichiers entier?
Léo Léopold Hertz 준영
2
Parce que sudo exécute la commande find avec les autorisations root, ce qui est fondamentalement une mauvaise idée. Les principes de ségrégation et de moindre privilège sont violés.
brouillard
3
L '"élévation" ici est des privilèges, à la racine, avec sudo. Vous risquez d'avoir tout votre système endommagé par un bogue findou 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.
tripleee
2

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:

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

Voir le problème clé ici est: ET / OU. Une bonne séquence de condition suggérée que je lis est:

-type d ! -readable ! -executable -prune

Cela ne fonctionne pas toujours. Cela signifie qu'un pruneau 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'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:

nice find / home * / -maxdepth 5 -suivre \
    \ (-type d -a ! \ (-readable -a -executable \) \) -prune \
    -o \
    \ (-type d -a -readable -a - exécutable -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, 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.

  • ¿Pourquoi utiliser la commande nice? J'ai eu l'idée ici . Au début, je pensais qu'il serait bien de réduire la priorité du 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 * /? Ce n'est pas pertinent pour ce fil. 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 binaires et versions cohabitant. J'ai besoin de localiser tous les répertoires, d'inspecter et de sauvegarder de manière maître-esclave. Je peux avoir plus d'un "/ 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, j'ai besoin de garder une trace des chemins absolus trouvés.
Jordi Ferran
la source
Merci pour votre réponse et belles observations! J'ai ouvert une prime ici pour mieux prévisualiser votre réponse. Je pense que c'est une bonne conclusion qui n'empêche pas l'accès en lecture et en exécution. - - Pouvez-vous expliquer pourquoi vous utilisez niceet find $HOME -maxdepth 5 -follow ...?
Léo Léopold Hertz 준영
2
Le script shell comme indiqué n'est pas à usage général (correspondant uniquement des répertoires listes ${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.
wjordan
2

Vous pouvez utiliser la correspondance inversée 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

Leonardo Hermoso
la source
2

- = Pour MacOS = -

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

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

et dans une nouvelle fenêtre de terminal, vous pouvez l'appeler:

$ file=<filename or mask>; search

par exemple:

$ file = etc; chercher

Jan aka uptech
la source
1

Si vous utilisez CSH ou TCSH, voici une solution:

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

Si vous souhaitez 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.

Kayle Sawyer
la source
Je veux grep tous les fichiers txt et exclure les fichiers / répertoires cachés, omettre le message "Autorisation refusée" à imprimer. J'utilise le shell csh. J'ai utilisé les commandes ci-dessous et elles ne fonctionnent pas. -type f -iname " .txt" -not -path '* / \. «| egrep -v "Autorisation refusée" trouver. -type f -iname " .txt" -not -path '* / \. '2> / dev / null Obtention sous l'erreur. find: les chemins doivent précéder l'expression: 2 Utilisation: find [-H] [-L] [-P] [-Olevel] [-D help | tree | search | stat | rates | opt | exec] [path ...] [Expression]
yadav