Como usar 'find -exec' para executar o comando no diretório do arquivo encontrado (não no diretório atual)?

4

Digamos que eu esteja em um diretório que tenha alguns subdiretórios, dir1 , dir2 e dir3 . Cada um desses diretórios tem um arquivo foo e eu gostaria de executar o mesmo comando em cada foo em cada um dos diretórios e ter esse comando executado dentro desse diretório.

Se eu fizesse "manualmente", seria algo parecido com isto:

cd dir1
(execute on foo)
cd ../dir2
(execute on foo)
cd ../dir3
(execute on foo)

É imperativo que o comando seja executado em cada um dos diretórios . foo é um script de agendamento em lote (para o HTCondor, se você quiser saber) e deve ser executado em cada subdiretório para que a saída das execuções iniciadas pelos scripts de agendamento acabe em cada subdiretório.

A pergunta " Encontre um arquivo e executar um comando no diretório do arquivo ", tanto quanto eu posso dizer, não responde a minha pergunta. A primeira resposta a essa pergunta é mais uma solução que não funcionará no meu caso, e a segunda resposta não tem uma explicação suficiente para eu saber como usá-la.

    
por Joshua 14.07.2016 / 22:34

2 respostas

11

Supondo que seu find ofereça suporte, use a opção -execdir em vez de -exec

find * -name 'foo' -execdir pwd \;

Se isso não acontecer, forneça detalhes da sua plataforma e / ou distribuição (conforme apropriado).

    
por 14.07.2016 / 22:38
1

Supondo que você saiba exatamente em quais diretórios executar seu comando,

for dir in dir1 dir2 dir3; do
    ( cd "$dir" && somecommand foo )
done

ou fazendo loop sobre os arquivos foo ,

for foo in */foo; do
  ( cd "${foo%/*}" && somecommand foo )
done

O subshell impede que o cd afete o diretório de trabalho do restante do script. A substituição do parâmetro ${foo%/*} se expande para o nome do diretório em que o arquivo foo mora (removendo tudo após o último / no valor de $foo ).

Usando o padrão find para fazer a mesma coisa (no caso em que os arquivos foo podem residir no fundo de uma estrutura de diretórios):

find . -type f -name foo -exec sh -c '
    for foo do
        ( cd "${foo%/*}" && somecommand foo )
    done' sh {} +

Em palavras: Encontre todos os arquivos regulares chamados "foo" em qualquer lugar no diretório atual ou abaixo e forneça seus nomes de caminho para este shell script em lotes. O script de shell deve iterar sobre os nomes de caminho fornecidos, alterar o diretório para a parte do diretório de cada nome de caminho e, se for bem-sucedido, executar somecommand foo .

Para uma solução que usa o -execdir não padrão, consulte a resposta do roaima . Sua resposta adaptou-se ao meu exemplo:

find . -type f -name foo -execdir somecommand foo ';'
    
por 04.07.2018 / 12:38

Tags