Comment maîtriser la commande UNIX find?


11

Je pense que je suis assez avancé dans mon utilisation de find, mais CHAQUE fois que je l'utilise, je ne peux pas me souvenir de la méthode pour fermer l'option -exec. Je passe beaucoup de temps à lire chaque fois que je l'utilise. Est-ce que je ne l'utilise pas assez ou n'attends pas trop de moi? Commençons par un exemple typique qui me frustre.

La structure du répertoire contient des fichiers avec toutes les autorisations incorrectes, des fichiers symboliques, des liens symboliques, etc. Je veux changer la propriété en une valeur raisonnable

find . -type f -exec chown username {} \;
find . -type d -exec chown username {} \;
find . -type d -exec chgrp usergroup {} \;
find . -type f -exec chgrp usergroup {} \;

(Pardonnez-moi si la fin est à l'envers ... Je l'ai regardé il y a une heure et je ne suis toujours pas sûr)

Mais j'ai peur de le faire fonctionner à cause des montures, des liens symboliques, etc. J'ai fait l'ultime gaffe de chmod. * Et je l'ai fait reculer sur moi avant. Je sais que -xdev renoncera à traverser les partitions mais je ne suis pas sûr de ce qui arrivera aux fichiers vivant dans les répertoires qui sont des liens symboliques.

Alors, comment maîtriser cette bête qui peut tuer des fichiers cruciaux?

Mettez à jour l' élagage des meilleures suggestions ci-dessous et résumant:

  1. Avoir un répertoire de pratique lié et monté à d'autres répertoires de pratique.
  2. Utilisez xargs plutôt que la commande exec non intuitive.
  3. Utilisez -exec echo {} pour la santé mentale et la sécurité
  4. Le point-virgule est spécial et vous y échappez donc le caractère d'échappement est d'abord
  5. La commande -or peut vous aider à combiner des critères de sélection.

Je suis un peu confus au sujet du print0 mais xargs a toujours été un peu sur la pratique pas facile à comprendre à première vue que j'essaie d'éviter.


1
Je ne m'en souviens pas non plus, donc je le fais juste passer en xargs.
résonateur

2
Lorsque vous êtes satisfait de la construction de la bonne commande, envisagez de l'exécuter avec + au lieu de \; Il s'exécutera plus rapidement avec + car la commande exec sera appelée beaucoup moins souvent.
wzzrd le

wzzrd, excellent conseil pour utiliser + plutôt que \;
Daniel Lawson

Réponses:


19

Eh bien, en ce qui concerne la -execsyntaxe, vous pourriez faire comme beaucoup de gens, abandonner et utiliser xargs:

find . -type f | xargs chown username

(ou la version fichiers-avec-espaces-et-autres-non-sens-in-them-safe)

find . -type f -print0 | xargs -0 chown username

Ou, pour essayer de vous rappeler la bonne chose à faire avec le point-virgule, ce que vous devez percer dans votre tête est que vous utilisez un point-virgule pour terminer la commande en -execcours d'exécution, et vous devez échapper au point-virgule car il a des ce qui signifie bash. C'est pourquoi il s'agit d'un point-virgule avec barre oblique inverse. Vous semblez avoir la {}partie de substitution d'accord.

Quant à tuer des fichiers et ainsi de suite, si vous exécutez quelque chose de gros et dangereux comme vous le dites, faites d'abord ceci:

find . -type f -exec echo chown username {} \;

et passer en revue les résultats. Il s'agit essentiellement d'un "essai à sec" où vous voyez les commandes qu'il exécuterait si vous le laissiez. Certainement une bonne pratique. N'aidera pas avec le .*problème, mais vous savez ne pas le faire maintenant. :)


1
+! pour la répétition sèche de l'écho. J'utilise toujours cela pour un grand changement
Steve Folly

3

Je suis surpris que personne n'ait encore mentionné l'option suivante:

find . -type f -ok chown username {} \;

Cette syntaxe confirmera la commande avant de l'exécuter. Cela fonctionne mieux si vous vous attendez à ce que votre correspondance soit un nombre relativement petit de fichiers, car cela vous demandera de les utiliser tous.

Certaines réponses le mentionnent xargs, mais avec GNU, cela n'est pas nécessaire non plus:

find . -type f -exec chown username {} \+

Notez que le + n'a généralement pas besoin d'être échappé, mais il est bon de prendre l'habitude de le faire de toute façon.


Pouvez-vous expliquer la nature du signe plus ... que fait-il exactement? Le shell le traite-t-il ou la commande? Je pense que je vais télécharger le code source de gnu-find car c'est un sujet intéressant.
ojblass

find le traite. Lisez man find pour en savoir plus sur cette option.
Kamil Kisiel

3

C'est à cela que sert l'homme: il peut être difficile de se souvenir des choses, c'est pourquoi la commande * nix inclut des pages de manuel. Vous pouvez toujours vérifier simplement la section ACTION de la page de manuel pour un rappel sur la syntaxe: man find. Bien que les pages de manuel puissent sembler peu conviviales, une fois que vous les maîtrisez, elles sont très pratiques.

Créer un frontal ou un wrapper: Quand je voulais améliorer GNU find, j'ai écrit un frontal graphique pour find qui génère des commandes find avec python, glade et pygtk. C'est un bon exercice si vous voulez vraiment bien le connaître.

Avoir un répertoire d'entraînement: Enfin, j'ai toujours un répertoire «scrap» dans mon répertoire personnel pour jouer avec des commandes puissantes lorsque quelque chose comme «echo» ne le coupe pas. Vous pouvez utiliser l'expansion du shell pour créer rapidement un tas de fichiers avec quelque chose comme:

for i in {1..100}; do touch "$i"; done

Un répertoire d'entraînement étrange est quelque chose que je n'ai jamais envisagé.
ojblass

1

Vous pouvez également combiner des expressions de recherche avec les opérateurs '-and' et '-or'. -et est implicite:

find . -type f -name "plainfile" ...

est le même que

find . -type f -and -name "plainfile" ...

L'opérateur or peut réduire votre liste de 4 commandes à 2:

find . -type d -or -type f ...

Et enfin, pas lié à la recherche, mais chown peut également définir le groupe. Donc, face aux espaces dans les noms, nous nous retrouvons avec:

find . -type d -or -type f -exec chown username:usergroup '{}' \;

Que trouve-t-on avec -ou le business. [Sic]
ojblass

@ojblass: find combine les expressions en utilisant 'et' ou 'ou', par défaut si ni '-and' ni '-or' ne sont spécifiés, '-and' est utilisé implicitement. Donc, tapez 'find -type d -type f' ne trouvera rien car rien n'est un répertoire et un fichier.
Steve Folly

0

Lors de la fermeture, je pense simplement à utiliser; comme avec de nombreux langages de programmation, puis y échapper. N'oubliez pas que cela doit être échappé et qu'il vous vient assez facilement.


0

Selon la version de find que vous utilisez, différentes options peuvent vous aider. La découverte GNU est probablement la plus puissante et cela peut vous aider avec votre deuxième question (implicite)

Par exemple - le comportement par défaut n'est pas de déréférencer les liens symboliques, mais vous pouvez remplacer cela; et l'option -mount empêche la recherche de traverser les points de montage

Regardez dans vos pages de manuel locales


0

Certains diront que l'option xargs est plus rapide que l'option -exec car elle n'exécutera pas la commande une fois pour chaque fichier, mais je ne m'inquiéterais pas de cela pour quoi que ce soit, sauf les travaux massifs prenant un temps non trivial.

Personnellement, je lance généralement find sans exec

find /path/to/dir -name whatever

assurez-vous que la sortie semble correcte, puis exécutez ma commande sur cette liste.

chown user:group `find /path/to/dir -name whatever`

Exemple parfait de la façon de «ne pas» faire les choses. Noms de fichiers avec espaces.
Ian Kelling

Oui, c'est un problème potentiel que j'aurais peut-être dû reconnaître. Cependant, mon point était de lire la sortie de recherche avant d'exécuter quoi que ce soit, où vous repéreriez des espaces ou d'autres folies de noms de fichiers.
theotherreceive

0

Pour certains shells (pas bash), échappez {} pour un comportement correct.

\{\} or '{}'

find manual est bon pour maîtriser find.


Non, non; find fonctionne très bien avec les {} tels quels. Ils font partie de la commande find: ils sont un jeton qui est remplacé par le résultat de la commande find. Ils ne signifient que quelque chose en bash lors de la définition de fonctions ou de l'appel de variables, vous pouvez donc simplement les utiliser comme dans la question d'origine.
wzzrd le

C'est à partir de la page de manuel. J'ai mis à jour pour dire que ce n'est pas applicable à bash.
Ian Kelling

0

Avant de faire quelque chose comme ça, assurez-vous que le répertoire contre lequel vous exécutez cette commande ne se trouve pas dans le même système de fichiers que / usr ou / etc. (sinon, si j'ai un lien dur vers / etc / passwd ou vers / bin / sh dans mon répertoire personnel, vous venez de m'en donner la propriété et comme effet secondaire, je possède maintenant la machine).

Si vous voulez recurer à travers un répertoire et afficher tous les fichiers / répertoires, un simple

chown -Rh user: utilisateur du groupe d'utilisateurs /

le fera. Assurez - vous que vous utilisez l'option -h ou chown suivrez les liens symboliques.


Je ne pense pas que ce soit multiplateforme. Échoue également avec 247 Ko de fichiers, comme le montre mon environnement de pratique. Je ne suis pas sûr pourquoi.
ojblass

Je pense que vous avez trouvé un bogue plus que vous avez trouvé un problème multiplateforme. Quelle version et quel est l'état de sortie en cas d'échec? Pour autant que je sache, il est originaire des premières versions bsd; c'est définitivement dans sunos 5.3 et ultrix et irix. Combien en traite-t-il avant d’échouer?
chris

Vous avez raison, cela fonctionne sur AIX 5.3, AIX 5.2, mais pas sur AIX 4.3, NCR, HP 11, HP 10.20 ou mes distributions DSL. Dans tous les cas, il semble échouer à ou près de 60k fichiers.
ojblass
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.