Expliquer les options -path et -prune de find

11

J'ai un script simple que je comprends le plus, c'est la commande find qui n'est pas claire. J'ai beaucoup de documentation mais ça ne sert pas à le rendre beaucoup plus clair. Ma pensée est que cela fonctionne comme une boucle for, le fichier actuellement trouvé est échangé pour {} et copié dans $ HOME / $ dir_name, mais comment fonctionne la recherche avec -path et -prune -o ? C'est ennuyeux d'avoir une documentation aussi spécifique et pertinente et de ne toujours pas savoir ce qui se passe.

#!/bin/bash
# The files will be search on from the user's home
# directory and can only be backed up to a directory
# within $HOME

read -p "Which file types do you want to backup " file_suffix
read -p "Which directory do you want to backup to " dir_name

# The next lines creates the directory if it does not exist
test -d $HOME/$dir_name || mkdir -m 700 $HOME/$dir_name

# The find command will copy files that match the
# search criteria ie .sh . The -path, -prune and -o
# options are to exclude the backdirectory from the
# backup.
find $HOME -path $HOME/$dir_name -prune -o \
-name "*$file_suffix" -exec cp {} $HOME/$dir_name/ \;
exit 0

C'est juste la documentation dont je sais que je devrais être capable de comprendre cela.

-modèle de chemin

Le nom de fichier correspond au modèle de motif de coque. Les métacaractères ne traitent pas / ou . spécialement; ainsi, par exemple, trouver. -path "./sr*sc" affichera une entrée pour un répertoire appelé ./src/misc (s'il en existe un). Pour ignorer une arborescence de répertoires entière, utilisez -prune plutôt que de vérifier chaque fichier de l'arborescence. Par exemple, pour ignorer le répertoire src / emacs et tous les fichiers et répertoires situés en dessous, et imprimer les noms des autres fichiers trouvés, faites quelque chose comme ceci:

find . -path ./src/emacs -prune -o -print

Du manuel Findutils

- Action: commande -exec; Cette variante non sécurisée de l' action -execdir est spécifiée par POSIX. La principale différence est que la commande est exécutée dans le répertoire à partir duquel find a été invoquée, ce qui signifie que {} est développé en un chemin relatif commençant par le nom de l'un des répertoires de départ, plutôt que simplement le nom de base du fichier correspondant.

Alors que certaines implémentations de find ne remplacent le {} que là où il apparaît de lui-même dans un argument, GNU find remplace {} partout où il apparaît.

Et

Par exemple, pour comparer chaque fichier d'en-tête C dans ou en dessous du répertoire actuel avec le fichier / tmp / master:

      find . -name '*.h' -execdir diff -u '{}' /tmp/master ';'
flerb
la source
Duplication possible de find: prune n'ignore pas le chemin spécifié
thecarpy
Je pense que si quelque chose est un doublon de find-path expliqué même si la réponse à find: prune n'ignore pas le chemin spécifié a une réponse qui semble s'appliquer à cette question. Peut-être que les réponses expliquées par le chemin de recherche ont du sens pour quelqu'un de plus expérimenté avec les scripts, mais elles ne m'aident pas. Jusqu'à présent, les réponses présentées ici ont plus de sens, même si je commence à peine à les examiner.
flerb

Réponses:

23

-pathfonctionne exactement comme -name, mais applique le modèle à l'ensemble du chemin d'accès du fichier examiné, au lieu du dernier composant.

-prune interdit de descendre en dessous du fichier trouvé, au cas où ce serait un répertoire.

Tout mettre ensemble, la commande

find $HOME -path $HOME/$dir_name -prune -o -name "*$file_suffix" -exec cp {} $HOME/$dir_name/ \;
  1. Commence la recherche de fichiers dans $HOME.
  2. S'il trouve un fichier correspondant, $HOME/$dir_nameil n'ira pas en dessous ("élague" le sous-répertoire).
  3. Sinon ( -o) s'il trouve un fichier correspondant, *$file_suffixil le copie $HOME/$dir_name/.

L'idée semble être de faire une sauvegarde de certains contenus de $HOMEdans un sous-répertoire de $HOME. Les pièces avec -prunesont évidemment nécessaires afin d'éviter de faire des sauvegardes de sauvegardes ...

AlexP
la source
Si je comprends bien: find parcourra tous les répertoires de $ HOME dans lesquels il dispose d'autorisations d'accès, à l'exception de $ HOME / $ dir_name, dans lequel il ne descendra pas (car l'action d'élagage aura la valeur true et le ou sera ne pas être pris), en recherchant les fichiers qui se terminent par $ file_suffix. Puis dès qu'il en trouve un, il exécutera cp "found_file.sh" dans $ HOME / $ dir_name? De plus, -path permet un chemin vers un fichier, et est utile lorsque vous voulez que find descende dans les répertoires et ne fonctionne pas seulement dans le répertoire courant?
flerb
Votre compréhension est presque correcte. -pathfonctionne comme -name: il sélectionne les fichiers. La différence est que -namecorrespond un modèle au nom de fichier, tandis que -pathcorrespond à un modèle au nom de chemin complet. finddescend toujours dans les sous-répertoires, sauf si empêché par -maxdepthou -pruneetc.
AlexP
Oh! -path est appliqué à $ HOME / $ dir_name -prune puis, c'est l'ordre des commandes qui me dérangeait, et -path est nécessaire pour la commande prune car il doit correspondre au chemin complet du répertoire élagué.
flerb
@Darren Je ne sais pas si c'est assez précis. -path $HOME/$dir_nameest une action. Il s'agit d'un test qui vérifie si le chemin du fichier en cours d'examen correspond à ce qui $HOME/$dir_nameest. -pruneest une action distincte. Je pense que la première phrase de votre premier commentaire reflète fidèlement comment cela fonctionne.
David Z
Serait-il manquant quelque chose pour le voir comme un tuyau? J'ai échangé -prune avec -print et je pense que le flux est clair maintenant: trouver $ HOME | -path $ HOME / $ dir_name | -print
flerb
4

Il fait partie de la commande find, l'instruction -exec.

Il vous permet d'interagir avec le fichier / répertoire trouvé par la findcommande.

find $HOME -path $HOME/$dir_name -prune -o -name "*$file_suffix" -exec cp {} $HOME/$dir_name/ \;

find $HOME signifie trouver des fichiers / répertoires dans $ HOME

Pour comprendre -path <some_path>, voir `find -path` expliqué

Pour comprendre -prune, voir /programming/1489277/how-to-use-prune-option-of-find-in-sh

-osignifie OU, donc -path <some_path>OU-name *$file_suffix

-exec signifie exécuter la commande.

cp {} $HOME/$dir_name/ copier tous les fichiers correspondant à $HOME/$dir_name/

\;signifie terminer la -execcommande

la carpe
la source