web-dev-qa-db-fra.com

trouver avec -execdir

Quand je cours find avec -execdir Je n'ai pas les résultats que je m'attendais.

Par exemple:

mkdir -p a/b/c
find . -type d -execdir touch foo \;
$ tree a
a
├── b
│   ├── c
│   └── foo
└── foo

Répertoire c ne contient pas de fichier foo. Comment puis-je obtenir find pour visiter et faire quelque chose localement dans chaque répertoire?

16

Pour chaque fichier correspondant (c'est-à-dire chaque répertoire), find passe au répertoire qui le contient (c'est-à-dire son répertoire parent) et exécute la commande spécifiée. Étant donné que la commande n'utilise pas le nom du match, il ne va jamais agir sur tous les répertoires. Pour cet arbre de répertoire particulier, vous faites

(cd . && touch foo)        # because ./a matches
(cd ./a && touch foo)      # because ./a/b matches
(cd ./a/b && touch foo)    # because ./a/b/c matches

Pour créer un fichier dans chaque répertoire, vous pouvez simplement utiliser -exec à la place de -execdir, à condition que votre implémentation de find permet {} À l'intérieur d'un argument (le plus, je pense que tous ceux):

find . -type d -exec touch {}/foo +

Pour la portabilité POSIX, vous aurez besoin de l'assemblage du nom du répertoire et du nom de base du fichier manuellement.

find . -type d -exec sh -c 'touch "$0/foo"' {} \;

ou (légèrement plus rapide)

find . -type d -exec sh -c 'for d; do touch "$d/foo"; done' _ {} +

Vous pouvez également utiliser la correspondance générique de faune récursive de Bash. Méfiez-vous que (contrairement à la fonctionnalité correspondante en KSH et à ZSH, et contrairement à votre commande find _ commande) Bash recoque sous des liens symboliques vers des répertoires.

shopt -s globstar
for d in **/*/; do touch -- "$d/foo"; done

Une solution ZSH:

touch ./**/(e\''REPLY+=foo'\')

La commande s'exécute dans chaque répertoire contenant un fichier correspondant. Etant donné que c ne contient pas de répertoire, il ne correspond pas et ne sera donc pas exécuté là-bas.

La solution consiste à ajouter le nom du répertoire à l'argument Execdir, comme:

find . -type d -execdir touch {}/foo \;
3
Jenny D

De man file

   -execdir command {} +
          Like  -exec,  but  the  specified  command is run from the subdirectory containing the matched file

Votre répertoire correspondant c vit dans le répertoire b, de sorte que l'exécutif est exécuté. Cela fonctionnerait comme vous vous attendez si vous recherchez des fichiers au lieu de répertoires.

Vous pouvez probablement réaliser ce que vous voulez en envoyant les répertoires à xargs comme cela sera fourni la liste complète des répertoires.

2
Matt