usando sed para substituir uma string em arquivos que estão em pastas diferentes

2

Eu tenho um arquivo que é colocado em pastas diferentes (com extensão de arquivo .mvw). Eu quero escrever um script que vai para cada pasta e substituir uma seqüência de caracteres (no arquivo * .mvw) "D3PLOT_1DForce" com o nome das pastas.

A estrutura da pasta

é a seguinte -

  • XYZ_DV_L02_P01
  • XYZ_DV_L02_P02
  • XYZ_DV_L02_P03

Eu escrevi o seguinte script -

#!/bin/sh
for ii in XYZ_DV_L02* ; do
(cd "$ii")
find . -iname "*.mvw" -type f -exec sed -i "s/D3PLOT_1DForce_EffPlStrainMax_VonMisesMax/"${ii}"/g" "{}" \;
done

Ele funciona e substitui a string pelo nome da pasta, mas está substituindo o nome da primeira pasta em todos os arquivos. Eu acho que sed não vai entrar em loop.

Como posso colocar o sed para funcionar no loop de forma que os respectivos nomes das pastas sejam usados para substituir a string no arquivo?

    
por Pavan Raj Singh 07.08.2018 / 21:05

3 respostas

4

O comando cd é executado em um sub shell e por isso efetivamente não faz nada. Portanto, o comando find é executado a partir do diretório pai, uma vez para cada um dos nomes de subdiretório em XYZ_DV_L02* . A primeira chamada de sed altera a string em todos os arquivos, as seguintes invocações de sed não localizam a string, mas são executadas de qualquer maneira.

Tente isto:

#!/bin/sh
for ii in XYZ_DV_L02* ; do
    find "$ii" -iname "*.mvw" -type f -exec sed -i "
      s/D3PLOT_1DForce_EffPlStrainMax_VonMisesMax/${ii}/g" "{}" +
done

Obrigado pela edição de Stéphane Chazelas

Embora tenha acabado de copiar o comando find da questão apenas corrigindo o caminho, vale a pena explicar as alterações:

  • ${ii} foi sem aspas, agora é parte das aspas que contêm todo o argumento sed .
  • Usar + em vez de \; fará com que find execute um comando sed para vários arquivos, não um para cada arquivo.

Editar

Para a solicitação do comentário, isso substituirá todas as seqüências do conjunto [-_a-zA-Z0-9] seguido por .h3d pelo texto de substituição, que é o nome do arquivo, incluindo a extensão .mvw , que é como eu entendo o comentário. mas não parece útil. Se você quiser acessar o texto no padrão, poderá usar . Você pode ter que adaptar o conjunto para suas necessidades particulares.

#!/bin/sh
for ii in XYZ_DV_L02* ; do
    find "$ii" -iname "*.mvw" -type f -exec sed -i -r "
      s/([-_a-zA-Z0-9]+)\.h3d/${ii}.h3d/g" "{}" +
done
    
por 07.08.2018 / 22:00
1

Tente isso,

#!/bin/sh
for ii in XYZ_DV_L02* ; do
cd "$ii"
find . -iname "*.mvw" -type f -exec sed -i "s/D3PLOT_1DForce/"${ii}"/g" "{}" \;
cd ..
done

É bom alterar o diretório para a primeira pasta de entrada em loop e encontrar o arquivo. Mas temos que voltar ao diretório pai antes de executar o próximo loop.

    
por 07.08.2018 / 21:22
1

Se você tiver uma estrutura de diretórios com apenas um número de subdiretórios, cada um com esse arquivo .mvw que deseja modificar, não será necessário usar find porque você já sabe exatamente onde seus arquivos estão .

for pathname in XYZ_DV_L02*/*.mvw; do
    sed -i "s/D3PLOT_1DForce/${pathname%%/*}/g" "$pathname"
done

Isso itera sobre todos os arquivos .mvw nos subdiretórios indicados e substitui a sequência pelo nome do diretório. A expansão do parâmetro ${pathname%%/*} exclui tudo após o primeiro / na sequência em $pathname .

Teste:

$ tree
.
|-- XYZ_DV_L02_P01
|   '-- somefile.mvw
|-- XYZ_DV_L02_P02
|   '-- somefile.mvw
'-- XYZ_DV_L02_P03
    '-- somefile.mvw

3 directories, 3 files

$ cat XYZ_DV_L02_P0*/*.mvw
Hello D3PLOT_1DForce_EffPlStrainMax_VonMisesMax!
Hello D3PLOT_1DForce_EffPlStrainMax_VonMisesMax!
Hello D3PLOT_1DForce_EffPlStrainMax_VonMisesMax!

(executando loop aqui)

$ cat XYZ_DV_L02_P0*/*.mvw
Hello XYZ_DV_L02_P01_EffPlStrainMax_VonMisesMax!
Hello XYZ_DV_L02_P02_EffPlStrainMax_VonMisesMax!
Hello XYZ_DV_L02_P03_EffPlStrainMax_VonMisesMax!

Obviamente, se você tiver uma hierarquia profunda, talvez seja necessário usar find , mas pode fazer o loop de dentro de find em vez de fora de find :

find XYZ_DV_L02*/ -type f -name '*.mvw' -exec sh -c '
    for pathname do
        sed -i "s/D3PLOT_1DForce/${pathname%%/*}/g" "$pathname"
    done' sh {} +

Aqui, encontramos todos os arquivos .mvw abaixo de qualquer diretório que corresponda ao padrão XYZ_DV_L02*/ . Para esses arquivos encontrados, executamos um loop que faz a mesma coisa que o loop no início desta resposta. Isso substituiria a string D3PLOT_1DForce em todos os arquivos .mvw em qualquer lugar abaixo de qualquer um dos diretórios com o nome do diretório XYZ_DV_L02* correspondente.

Relacionados:

Esta resposta assume o GNU sed ou alguma outra implementação sed que edita no local com -i sem um argumento de opção.

    
por 08.08.2018 / 08:14