Comment puis-je exclure tous les messages "permission denied" de "find"?
j'ai besoin de masquer tous les permission denied messages à partir de:
find . > files_and_folders
j'expérimente quand un tel message apparaît. Je dois rassembler tous les dossiers et les fichiers, à laquelle il ne se pose pas.
est-il possible d'Orienter les niveaux de permission vers le fichier files_and_folders
?
Comment puis-je Cacher les erreurs en même temps?
18 réponses
Note:
* Cette réponse va probablement plus loin que le cas d'utilisation le justifie, et find 2>/dev/null
peut être suffisant dans de nombreuses situations. Il peut encore être intéressant pour une perspective inter-plate-forme et pour sa discussion de certaines techniques avancées de shell dans l'intérêt de trouver une solution qui est aussi robuste que possible, même si les cas protégés contre peuvent être largement hypothétique.
* Si votre système est configuré pour afficher localisé messages d'erreur , préfixer les appels find
ci-dessous avec LC_ALL=C
( LC_ALL=C find ...
) pour s'assurer que anglais messages sont signalés, de sorte que grep -v 'Permission denied'
fonctionne comme prévu. Invariablement, cependant, les messages d'erreur faire affiché sera ensuite en anglais.
si votre est bash
ou zsh
, il y a une solution qui est robuste tout en étant raisonnablement simple , en utilisant seulement conforme POSIX find
caractéristiques ; alors que bash
elle-même ne fait pas partie de POSIX, la plupart des plates-formes Unix modernes viennent avec elle, ce qui rend cette solution largement portable:
find . > files_and_folders 2> >(grep -v 'Permission denied' >&2)
Note: Il y a une petite chance que certains de grep
de sortie peut arriver après find
complète, parce que la commande globale n'attend pas la commande à l'intérieur de >(...)
pour finir. Dans bash
, vous pouvez empêcher cela en ajoutant | cat
à la commande.
-
>(...)
est un (rarement utilisé) sortie substitution de processus qui permet de rediriger la sortie (dans ce cas, stderr sortie (2>
) vers le stdin de la commande à l'intérieur de>(...)
.
En plus debash
, etzsh
,ksh
les supporte aussi en principe , mais en essayant de les combiner avec une redirection de stderr , comme c'est fait ici (2> >(...)
), semble être silencieusement ignoré (dansksh 93u+
).-
grep -v 'Permission denied'
filters out (-v
) toutes les lignes (à partir dufind
command's stderr stream) qui contient la phrasePermission denied
et affiche les lignes restantes vers stderr (>&2
).
-
Cette approche est:
-
robuste :
grep
est seulement appliqué à messages d'erreur (et non à une combinaison de chemins de fichier et messages d'erreur, conduisant potentiellement à des faux positifs), et messages d'erreur autres que ceux qui ne sont pas autorisés sont transmis à stderr. -
sans effet secondaire :
find
le code de sortie de "est préservé: l'impossibilité d'accéder à au moins un des éléments du système de fichiers rencontrés se traduit par le code de sortie1
(bien que cela ne vous dira pas si les erreurs autre que celles avec permission refusée se sont produites (aussi)).
POSIX-compliant solutions:
Les solutions entièrement conformes à la normeentièrement conformes à la norme POSIX ont des limites ou nécessitent des travaux supplémentaires.
si la sortie de find
doit être saisie dans un fichier de toute façon (ou supprimée complètement), alors la solution basée sur le pipeline de 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 questions: 2>&1
doit venir première .
Capture stdout dans un fichier à l'avant permet de 2>&1
envoyer seulement "1519860920 des messages d'erreur" à travers le pipeline, qui grep
peut alors fonctionner sans ambiguïté.
le seul inconvénient est que le code de sortie global sera le grep
commande , pas find
's, qui dans ce cas signifie: s'il y a Non erreurs du tout ou seulement permission-denied errors, the exit code will be 1
(signaling failure ), sinon (erreurs autres que permission-denied ones) 0
- ce qui est le contraire de l'intention.
cela dit, find
code de sortie est rarement utilisé , car il communique souvent peu d'information au-delà de défaillance" fondamentale telle que le passage d'un chemin inexistant.
Cependant, le cas spécifique de ne serait-ce que quelque des chemins d'entrée étant inaccessible en raison du manque de permissions est reflété dans le code de sortie de find
(à la fois dans GNU et BSD find
): si une erreur de permissions-denied se produit pour toute de la fichiers traités, le code de sortie est défini à 1
.
la variation suivante tient compte de 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 Permission denied
se sont produites: 1
si oui, 0
autrement.
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 pas d'erreurs ou seulement des erreurs ont été commises.
C'est sans doute encore mieux que de simplement passer le code de sortie de find
, comme dans la solution en haut.
gniourf_gniourf dans les commentaires propose une (encore conforme POSIX) généralisation de cette solution en utilisant des redirections sophistiquées , qui fonctionne même avec le comportement par défaut de l'impression des chemins de fichier 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 seul peuvent être pipés à grep
via stdout.
sans ces redirections, les deux données (chemins de fichier) et messages d'erreur serait acheminé à grep
via stdout, et grep
ne serait alors pas en mesure de distinguer entre message d'erreur Permission denied
et un (hypothétique) fichier dont le nom contient l'expression Permission denied
.
Comme dans la première solution, cependant, le code de sortie signalé sera grep
, pas find
, mais le même correctif comme ci-dessus peuvent être appliquées.
Notes sur les réponses:
-
il y a plusieurs points à noter au sujet de réponse de Michael Brux ,
find . ! -readable -prune -o -print
:-
Il faut GNU
find
; notamment, il ne fonctionnera pas sur macOS. Bien sûr , si vous avez seulement besoin de la commande pour travailler avec GNUfind
, ce ne sera pas un problème pour vous. -
Certains
Permission denied
erreurs encore surface:find ! -readable -prune
les rapports de ces erreurs pour le enfant éléments de répertoires pour lesquels l'utilisateur actuel n'ontr
la permission, mais manque dex
(exécutable) autorisation. La raison 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 pour la permissionr
d'être absent. -
Note: 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 répond bien à vos besoins, surtout si simplement impression les chemins est tout ce que vous faites:
- Si vous conceptualiser le filtrage de l'autorisation, de refus d'erreur les messages d'un séparé la tâche que vous voulez être en mesure de s'appliquer à tout "151950920 de la commande", puis à l'opposé de l'approche de façon proactive prévention l'autorisation des erreurs de refus nécessite l'introduction de "bruit" dans le "151950920 de la commande", qui introduit aussi la complexité et logique pièges .
- par exemple, le commentaire le plus voté sur la réponse de Michael (en date de cette écriture) tente de montrer comment étendre la commande en incluant un filtre
-name
, comme suit:
find . ! -readable -prune -o -name '*.txt'
Cela, cependant, ne fonctionne pas comme prévu, parce que l'arrière-print
action est requis (an explication peut être trouvée dans cette réponse ). Ces subtilités peuvent introduire des bogues.
-
-
La première solution dans le Jonathan Leffler la réponse de ,
find . 2>/dev/null > files_and_folders
, comme il l'a lui-même déclare, à l'aveuglette silences tous messages d'erreur (et la solution de contournement est lourd et n'est pas entièrement solide, comme il l'a aussi expliquer.) pragmatiquement parlant , 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 mist ,
sudo find . > files_and_folders
, est concis et pragmatique, mais mal avisé pour tout autre que simplement impression noms de fichiers , pour la sécurité raisons: parce que vous êtes en cours d'exécution en tant que root user, "vous risquez d'avoir tout votre système être perturbé par un bug dans find 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 avez couru cela avec des privilèges normaux" (d'un commentaire sur la réponse de mist par tripleee ). -
La 2ème solution dans viraptor réponse ,
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 à travers le pipeline), et, potentiellement, au lieu de signaler non - permission-denied errors via stderr, les capture le long des chemins de sortie dans le fichier de sortie.
Utiliser:
find . 2>/dev/null > files_and_folders
cela cache non seulement les erreurs Permission denied
, 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 la permission refusée ceux, alors vous auriez probablement à prendre une supposition volante que vous n'avez pas beaucoup de fichiers appelés 'permission refusée' et essayer:
find . 2>&1 | grep -v 'Permission denied' > files_and_folders
Si vous strictement vous voulez filtrer 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: 2>&1 > files_and_folders |
.
Le tuyau redirige la sortie standard vers la commande grep
et est appliqué en premier. Le 2>&1
envoie l'erreur standard au même endroit que la sortie standard (le tuyau). Le > files_and_folders
envoie la sortie standard (mais pas l'erreur standard) à un fichier. Le résultat net est que les messages écrits à la norme les erreurs sont envoyées dans le tuyau et la sortie régulière de find
est écrite dans le fichier. Le grep
filtre la sortie standard (vous pouvez décider à quel point vous voulez qu'elle soit sélective, et peut avoir à changer l'orthographe en fonction de la locale et O/S) et le >&2
final signifie que les messages d'erreur survivants (écrits à la sortie standard) aller à l'erreur standard une fois de plus. La redirection peut être considéré comme facultatif à la borne, mais serait une très bonne idée de l'utiliser dans un script, de sorte que les messages d'erreur apparaissent sur l'erreur standard.
il y a 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é de shell Bourne (Bash, Korn, ...) et n'importe quelle version find
.
Si vous souhaitez adapter à la version spécifique de find
que vous avez sur votre système, il peut y avoir d'autres options 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.
Utiliser:
find . ! -readable -prune -o -print
ou plus généralement
find <paths> ! -readable -prune -o <other conditions like -name> -print
- pour éviter "Permission refusée"
- et ne suppriment pas les messages d'erreur (autres)
- et obtenir le statut de sortie 0 ("tous les fichiers sont traités avec succès")
fonctionne avec: find (GNU findutils) 4.4.2. Historique:
- l'essai
-readable
correspond aux fichiers lisibles. L'opérateur!
renvoie true, lorsque le test est faux. Et! -readable
correspond à des répertoires (&fichiers) non lisibles. - l'action
-prune
ne descend pas dans directory. -
! -readable -prune
peut être traduit en: si le répertoire n'est pas lisible, ne pas y descendre. - le test
-readable
prend en compte les listes de contrôle d'accès et autres permissions artéfacts que le-perm
le test ignore.
Voir aussi find
(1) page de manuel pour beaucoup plus de détails.
si vous voulez lancer la recherche à partir de la racine "/", vous verrez probablement sortir quelque chose comme:
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:
-
vous pouvez utiliser la commande sudo:
sudo find /. -name 'toBeSearched.file'
. il demande le mot de passe du super utilisateur, quand entrez le mot de passe, vous verrez le résultat que vous voulez vraiment. -
vous pouvez utiliser rediriger la sortie D'erreur Standard de (généralement Display / Screen) à certains fichiers et éviter de voir les messages d'erreur sur l'écran! rediriger vers un fichier spécial /dev/null :
find /. -name 'toBeSearched.file' 2>/dev/null
-
vous pouvez utiliser rediriger la sortie D'erreur Standard de (généralement affichage / écran) vers la sortie Standard (généralement affichage / écran), puis pipe avec la commande grep avec le paramètre-v "inverse" pour ne pas voir les lignes de sortie qui ont' Permission denied 'des paires de mots:
find /. -name 'toBeSearched.file' 2>&1 | grep -v 'Permission denied'
j'ai dû utiliser:
find / -name expect 2>/dev/null
spécifiant le nom de ce que je voulais trouver et lui disant de rediriger toutes les erreurs vers /dev / null
expect est l'emplacement du programme expect que je cherchais.
Pipe stderr
à /dev/null
à l'aide de 2>/dev/null
find . -name '...' 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 puis-je supprimer les instructions" permission denied " du programme find? - 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 rediriger l'erreur standard vers /dev/null comme ceci:
find . 2>/dev/null >files_and_folders
alors que les approches ci-dessus ne traitent pas le cas de Mac OS X parce que Mac Os X ne supporte pas le commutateur -readable
c'est comme ça que vous pouvez éviter les erreurs "Permission denied" 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$
.
renvoie la taille totale des fichiers d'un motif donné. Notez le 2>/dev/null
à la fin de la commande rechercher.
ces erreurs sont imprimées sur la sortie standard error (fd 2). Pour les filtrer, redirigez simplement toutes les erreurs vers /dev / null:
find . 2>/dev/null > some_file
ou d'abord joindre stderr et stdout et ensuite grep 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
) de sorte que tous les messages d'erreur sont réduits au silence.
- le code de sortie sera toujours
1
s'il y a lieu"Permission denied
"les erreurs seraient autrement imprimées
réponse robuste pour GNU find
:
find . -type d \! \( -readable -executable \) -prune -print -o -print > files_and_folders
passer les options supplémentaires à find
que -prune
(empêcher de descendre dans) mais tout de même -print
n'importe quel répertoire ( -type
d
) ce n'est pas ( \!
) ont à la fois les autorisations -readable
et -executable
, ou ( -o
) -print
tout autre dossier.
-
-readable
et-executable
les options sont des extensions GNU, ne font pas partie du POSIX standard - peut toujours revenir "
Permission denied
" sur les fichiers anormaux/corrompus (par exemple, voir rapport de bogue affectant les systèmes de fichiers montés surlxcfs
< v2.0.5)
réponse robuste qui fonctionne avec N'importe quel 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 passer le flux d'erreur standard à grep
, suppression de toutes les lignes contenant la chaîne 'Permission denied'
.
LC_ALL=C
ensembles le POSIX locale utilisant une variable d'environnement , 3>&2 2>&1 1>&3
et 3>&2 2>&1
duplicate file descriptors pour conduire le flux d'erreur standard à grep
, et [ $? = 1 ]
utilise []
pour inverser le code d'erreur retourné par grep
pour se rapprocher du comportement original de find
.
- filtrera également toute erreur
'Permission denied'
due à une redirection de sortie (par exemple, si le fichierfiles_and_folders
lui-même n'est pas accessible en écriture)
pour éviter juste la permission a refusé les Avertissements, dire à find d'ignorer les fichiers illisibles en les élaguant de la recherche. Ajouter une expression comme ou à votre find, telle que
find / \! -readable -prune -o -name '*.jbd' -ls
Ce la plupart du temps dit (match un fichier illisible et le tailler à partir de la liste) OU (correspondance avec un nom comme *.jbd et de l'afficher [ls]) . (Rappelez-vous que par défaut, la expressions ET serions ensemble, sauf si vous utilisez ou.) Vous avez besoin de l'option-ls dans la seconde expression ou alors find peut ajouter une action par défaut pour afficher l'une ou l'autre correspondance, ce qui vous montrera aussi tous les fichiers illisibles.
mais si vous cherchez des fichiers réels sur votre système, il n'y a généralement aucune raison de chercher dans /dev, qui a beaucoup de fichiers, donc vous devriez ajouter une expression qui exclut ce répertoire, comme:
find / -mount \! -readable -prune -o -path /dev -prune -o -name '*.jbd' -ls
Donc (match fichier illisible et prune de la liste) ou (match path /dev et prune de la liste) ou (match file like *.jbd et l'afficher) .
utiliser
sudo find / -name file.txt
c'est stupide (parce que vous élevez la recherche) et non sûr, 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 gère correctement le processus de retour de code / sortie de code. J'utilise la commande find dans les scripts bash pour localiser certains répertoires et ensuite inspecter leur contenu. J'évalue la commande find success en utilisant le code exit: une valeur zéro fonctionne, sinon échoue.
Le réponse ci-dessus par Michael Brux fonctionne parfois. Mais Je avoir un scénario dans lequel il ne! J'ai découvert le problème et résolu moi-même. Je dois tailler les fichiers quand:
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 que j'ai Lu est:
-type d ! -readable ! -executable -prune
Cela ne fonctionne pas toujours. Cela signifie qu'un prune est déclenché quand 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 qu'aucun accès en exécution ne l'est.
après quelques tests j'ai réalisé à ce sujet et j'ai changé ma solution de script shell en:
nice find / home* / - maxdepth 5-follow \
\( -type d -un ! \ (lisible par un exécutable \) \) -prune \
-o \
\( -type d -un -lisible -un -exécutable -un -nom "${m_find_name}" \) -impression
La clé ici est de placer le "pas vrai" pour une expression:
has read access AND has execute access
sinon il n'a pas un accès complet, ce qui signifie: taillez-le. Cela a fonctionné 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épart, j'ai pensé qu'il serait bien de réduire la priorité des processus lorsque l'on regarde tout un système de fichiers. 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 plus pertinente pour ce thread. J'installe toutes les applications à la main via le code source compiler avec des utilisateurs non privilégiés (pas root). Ils sont installés dans "/ home". Je peux avoir plusieurs binaires. et des versions vivant ensemble. Je dois localiser tous les répertoires, inspecter et sauvegarder de façon maître-esclave. Je peux avoir plus d'un "/home" (plusieurs disques tournant sur un serveur dédié).
- ¿Pourquoi utiliser-suivre? Les utilisateurs peuvent créer des liens symboliques vers des répertoires. Son utilité dépend, j'ai besoin de noter les chemins absolus trouvés.
vous pouvez utiliser le grep-v invert-match
-v, --invert-match select non-matching lines
comme ceci:
find . > files_and_folders
cat files_and_folders | grep -v "permission denied" > files_and_folders
devrait à la magie
- = Pour MacOS= -
crée une nouvelle commande en utilisant alias: il suffit d'ajouter ~/.bash_profile ligne:
alias search='find / -name $file 2>/dev/null'
et dans la nouvelle fenêtre du Terminal vous pouvez l'appeler:
$ file=<filename or mask>; search
par exemple:
$ fichier=etc; la recherche
si vous utilisez CSH ou TCSH, voici une solution:
( find . > files_and_folders ) >& /dev/null
si vous voulez la 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 aussi une solution facile à mettre vos résultats de recherche dans un fichier.
trouver . - nom 'NameOfSearchedFile' >> résultats.txt