sed - simple - Alterar vários arquivos




moodle simple certificate plugin (6)

O comando a seguir está alterando corretamente o conteúdo de dois arquivos.

sed -i 's/abc/xyz/g' xaa1 xab1 

Mas o que eu preciso fazer é alterar vários desses arquivos dinamicamente e não sei os nomes dos arquivos. Eu quero escrever um comando que vai ler todos os arquivos do diretório atual, começando com xa* e sed deve alterar o conteúdo do arquivo.


Esses comandos não funcionam no sed padrão que vem com o Mac OS X.

Do man 1 sed :

-i extension
             Edit files in-place, saving backups with the specified
             extension.  If a zero-length extension is given, no backup 
             will be saved.  It is not recommended to give a zero-length
             extension when in-place editing files, as you risk corruption
             or partial content in situations where disk space is exhausted, etc.

Tentou

sed -i '.bak' 's/old/new/g' logfile*

e

for i in logfile*; do sed -i '.bak' 's/old/new/g' $i; done

Ambos funcionam bem.


Estou surpreso que ninguém tenha mencionado o argumento -exec para localizar, que é destinado a esse tipo de caso de uso, embora ele inicie um processo para cada nome de arquivo correspondente:

find . -type f -name 'xa*' -exec sed -i 's/asd/dsg/g' {} \;

Como alternativa, pode-se usar xargs, que invocarão menos processos:

find . -type f -name 'xa*' | xargs sed -i 's/asd/dsg/g'

Ou simplesmente use a variante + exec em vez de ; em find para permitir que o find forneça mais de um arquivo por chamada de subprocesso:

find . -type f -name 'xa*' -exec sed -i 's/asd/dsg/g' {} +

Melhor ainda:

for i in xa*; do
    sed -i 's/asd/dfg/g' $i
done

porque ninguém sabe quantos arquivos existem, e é fácil quebrar os limites da linha de comando.

Veja o que acontece quando há muitos arquivos:

# grep -c aaa *
-bash: /bin/grep: Argument list too long
# for i in *; do grep -c aaa $i; done
0
... (output skipped)
#

Outra maneira mais versátil é usar o find :

sed -i 's/asd/dsg/g' $(find . -type f -name 'xa*')

Você poderia usar grep e sed juntos. Isso permite que você pesquise subdiretórios recursivamente.

Linux: grep -r -l <old> * | xargs sed -i 's/<old>/<new>/g'
OS X: grep -r -l <old> * | xargs sed -i '' 's/<old>/<new>/g'

For grep:
    -r recursively searches subdirectories 
    -l prints file names that contain matches
For sed:
    -i extension (Note: An argument needs to be provided on OS X)

você pode fazer

' xxxx ' text u search e irá substituí-lo por ' yyyy '

grep -Rn '**xxxx**' /path | awk -F: '{print $1}' | xargs sed -i 's/**xxxx**/**yyyy**/'