cd em todos os diretórios, execute o comando em arquivos nesse diretório e retorne ao diretório atual anterior

33

Estou tentando escrever um script que será executado em um determinado diretório com muitos subdiretórios de nível único. O script fará cd em cada um dos subdiretórios, executará um comando nos arquivos do diretório e fará o cd-out para continuar no próximo diretório. Qual é a melhor maneira de fazer isso?

    
por Something Jones 05.12.2014 / 16:29

5 respostas

68
for d in ./*/ ; do (cd "$d" && somecommand); done
    
por 05.12.2014 / 16:32
12

A melhor maneira é não usar cd :

find some/dir -type f -execdir somecommand {} \;

execdir é como exec , mas o diretório de trabalho é diferente:

   -execdir command {} [;|+]
          Like   -exec,   but  the  specified  command  is  run  from  the
          subdirectory containing the matched file, which is not  normally
          the  directory  in  which  you  started  find.  This a much more
          secure  method  for  invoking  commands,  as  it   avoids   race
          conditions  during resolution of the paths to the matched files.

Não é POSIX.

    
por 05.12.2014 / 16:31
2
cd -P .
for dir in ./*/
do cd -P "$dir" ||continue
   printf %s\n "$PWD" >&2
   command && cd "$OLDPWD" || 
! break; done || ! cd - >&2

O comando acima não precisa fazer nenhum subshell - ele apenas rastreia seu progresso no shell atual, alternando $OLDPWD e $PWD . Quando você cd - o shell troca o valor dessas duas variáveis, basicamente, conforme ele muda de diretório. Também imprime o nome de cada diretório enquanto ele trabalha lá para stderr.

Acabei de dar uma segunda olhada e decidi que poderia fazer um trabalho melhor com o tratamento de erros. Ele ignorará um dir no qual ele não pode cd - e cd imprimirá uma mensagem sobre o porquê de stderr - e será break w / um código de saída diferente de zero se seu command não for executado com êxito ou Se a execução de command de alguma forma afetar sua capacidade de retornar ao diretório original - $OLDPWD . Nesse caso, ele também executa cd - last - e grava o nome do diretório de trabalho atual resultante em stderr.

    
por 05.12.2014 / 17:17
2
pushd subdir
# do stuff
popd

pushd / popd são bash builtins que fornecem uma pilha de diretórios. Você pode fazer vários pushd s e depois vários popd s e voltar para onde começou. Você também pode manipular a pilha com dirs .

Como um bash embutido, a documentação está no bash manpage ( man 1 bash e pesquisa ( / ) para pushd, n para avançar nos resultados da pesquisa) ou use help pushd help popd help dirs .

    
por 06.12.2014 / 00:25
1
for D in ./*; do
    if [ -d "$D" ]; then
        cd "$D"
        run_something
        cd ..
    fi
done
    
por 05.12.2014 / 16:39