encontrar com -execdir

13

Quando executo find com -execdir , não obtenho os resultados esperados.

Por exemplo:

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

O diretório c não contém um arquivo foo . Como obtenho o find para visitar e fazer algo localmente em cada diretório?

    
por Marcus Junius Brutus 07.01.2014 / 16:01

3 respostas

13

Para cada arquivo correspondente (ou seja, todos os diretórios), find alterna para o diretório que o contém (ou seja, seu diretório pai) e executa o comando especificado. Como o comando não usa o nome da correspondência, ele nunca atuará em todos os diretórios. Para esta árvore de diretórios específica, você está fazendo

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

Para criar um arquivo em cada diretório, você pode simplesmente usar -exec em vez de -execdir , desde que sua implementação de find permita {} dentro de um argumento (a maioria faz e, em particular, acho que todos ):

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

Para portabilidade POSIX, você precisaria fazer a montagem do nome do diretório e o nome da base do arquivo manualmente.

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

ou (um pouco mais rápido)

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

Como alternativa, você pode usar a correspondência curinga recursiva do bash. Cuidado (ao contrário do recurso correspondente em ksh e zsh, e ao contrário do comando find ) bash recursiva sob links simbólicos para diretórios.

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

Uma solução zsh:

touch ./**/(e\''REPLY+=foo'\')
    
por 08.01.2014 / 01:56
3

O comando é executado em todos os diretórios que contenham um arquivo correspondente. Como c não contém um diretório, ele não corresponde e, portanto, não será executado lá.

A solução é adicionar o nome do diretório ao argumento execdir, da seguinte forma:

find . -type d -execdir touch {}/foo \;
    
por 07.01.2014 / 16:08
2

De man file

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

Seu diretório correspondente c reside no diretório b , de modo que é a partir de onde o exec é executado. Funcionaria como você espera se você estiver procurando por arquivos em vez de diretórios.

Você provavelmente conseguirá o que deseja enviando os diretórios para xargs , já que será fornecida a lista completa de diretórios.

    
por 07.01.2014 / 16:08