trouver avec -execdir

15

Quand je cours findavec, -execdirje n'obtiens pas les résultats que j'attendais.

Par exemple:

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

Le répertoire cne contient pas de foofichier. Comment puis-je findvisiter et faire quelque chose localement dans chaque répertoire?

Marcus Junius Brutus
la source

Réponses:

18

Pour chaque fichier correspondant (c'est-à-dire chaque répertoire), findbascule vers le répertoire qui le contient (c'est-à-dire son répertoire parent) et exécute la commande spécifiée. Puisque la commande n'utilise pas le nom de la correspondance, elle n'agira jamais sur tous les répertoires. Pour cette arborescence de répertoires particulière, 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 à la -execplace de -execdir, à condition que votre implémentation de findpermet à l' {}intérieur d'un argument (la plupart le font, et en particulier je pense que tous):

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

Pour la portabilité POSIX, vous devez effectuer manuellement l'assemblage du nom du répertoire et du nom de la base de fichiers.

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 récursive générique de bash. Attention (contrairement à la fonctionnalité correspondante dans ksh et zsh, et contrairement à votre findcommande) bash revient 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'\')
Gilles 'SO- arrête d'être méchant'
la source
FYI: man bashétats sous "-c": les arguments après chaîne_commande sont assignés aux paramètres positionnels commençant par $ 0, cependant "for d" parcourra les paramètres positionnels commençant par $ 1. "_" est un texte affecté à $ 0 et qui ne sera pas utilisé.
Chad Skeeters
3

La commande s'exécute dans chaque répertoire contenant un fichier correspondant. Puisquec 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 ceci:

find . -type d -execdir touch {}/foo \;
Jenny D
la source
2

De man file

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

Votre répertoire correspondant créside dans leb répertoire, c'est de là que s'exécute l'exec. Cela fonctionnerait comme prévu si vous recherchez des fichiers au lieu de répertoires.

Vous pourriez probablement obtenir ce que vous voulez en envoyant les répertoires, xargscar la liste complète des répertoires sera fournie.

Mat
la source