Eu preciso procurar recursivamente por uma seqüência especificada dentro de todos os arquivos e subdiretórios dentro de um diretório e substituí-la por outra.
Eu sei que o comando para encontrá-lo pode ficar assim:
grep 'string_to_find' -r ./*
Mas como posso substituir todas as instâncias string_to_find
por outra string?
sed -i 's/.*substring.*/replace/'
sed -i 's/\(.*\)substring\(.*\)/\1replace\2/'
Respostas:
Outra opção é usar o find e passá-lo pelo sed.
fonte
-i
é necessária uma sequência de extensão adequada para o parâmetro . Por exemplo,find /path/to/files -type f -exec sed -i "" "s/oldstring/new string/g" {} \;
qualquer forma, proporcionando string vazia ainda cria um arquivo de backup ao contrário descritas no manual ...-i ""
para o OS X. Funciona de outra forma.CRLF
paraLF
no Windows.Eu tenho a resposta.
fonte
grep
e novamente comsed
. Usar ofind
método é mais eficiente, mas esse método que você mencionou funciona.sed -i 's/str1/str2/g'
parased -i "" 's/str1/str2/g'
para que isso funcione.grep
percorre todos os arquivos esed
verifica apenas os arquivos correspondentesgrep
. Com ofind
método na outra resposta,find
primeiro lista todos os arquivos e, em seguidased
, varre todos os arquivos desse diretório. Portanto, esse método não é necessariamente mais lento, depende de quantas correspondências existem e das diferenças nas velocidades de pesquisa entresed
,grep
efind
.Você poderia até fazer assim:
Exemplo
Isso procurará pela string ' windows ' em todos os arquivos relativos ao diretório atual e substituirá ' windows ' por ' linux ' para cada ocorrência da string em cada arquivo.
fonte
grep
só é útil se houver arquivos que não devem ser modificados. A execuçãosed
de todos os arquivos atualizará a data de modificação do arquivo, mas manterá o conteúdo inalterado se não houver correspondências.-i
, acredito quesed
altera o tempo do arquivo de todos os arquivos em que ele toca, mesmo que o conteúdo não seja alterado.sed
também converte as terminações de linha . Eu não usosed
no Windows em um repositório git, porque todosCRLF
são alteradas paraLF
.Isso funciona melhor para mim no OS X:
Fonte: http://www.praj.com.au/post/23691181208/grep-replace-text-string-in-files
fonte
ag "search" -l -r . | sort | uniq | xargs perl -e 's/search/replace' -pi
sort -u
parte uniforme disso? Em que circunstâncias você esperariagrep -rl
produzir o mesmo nome de arquivo duas vezes?Outras soluções combinam sintaxes regex. Para usar padrões de perl / PCRE para ambos pesquisa e substituição, e somente os arquivos de correspondência de processos, isso funciona muito bem:
onde
match1
ematch2
geralmente são idênticos, masmatch1
podem ser simplificados para remover recursos mais avançados que são relevantes apenas para a substituição, por exemplo, grupos de captura.Tradução:
grep
recursivamente e liste os arquivos que correspondem a esse padrão PCRE, separados por nul para proteger caracteres especiais no nome do arquivo e canalize os nomes de arquivos nosxargs
quais está esperando uma lista separada por nulos, mas não fará nada se nenhum nome for recebido, eperl
substitua as linhas onde as correspondências são encontradas.Adicione a
I
opçãogrep
para ignorar arquivos binários. Para correspondência com distinção entre maiúsculas e minúsculas, solte oi
comutador degrep
e oi
sinalizador anexado à expressão de substituição, mas não oi
comutador emperl
si.fonte
find2perl
que acompanha o Perl que faz esse tipo de coisa sem nenhumxargs
truque.find
não pesquisa o conteúdo do arquivo, e o objetivo é processar apenas os arquivos correspondentes sem escrever um programa Perl.Geralmente não com grep, mas com
sed -i 's/string_to_find/another_string/g'
ouperl -i.bak -pe 's/string_to_find/another_string/g'
.fonte
Tenha muito cuidado ao usar
find
esed
em um repositório git! Se você não excluir os arquivos binários, poderá acabar com este erro:Para resolver esse erro, você precisa reverter o
sed
seu, substituindo o seunew_string
pelo seuold_string
. Isso reverterá as seqüências substituídas, e você voltará ao início do problema.A maneira correta de procurar por uma string e substituí-la é pular
find
e usargrep
para ignorar os arquivos binários:Créditos para @hobs
fonte
Aqui está o que eu faria:
isso procurará todos os arquivos que contenham
filename
o nome do arquivo, abaixo de/path/to/dir
, para cada arquivo encontrado, procure a linha comsearchstring
e substituaold
pornew
.Porém, se você deseja omitir a procura de um arquivo específico com uma
filename
string no nome do arquivo, simplesmente faça:Isso fará o mesmo acima, mas para todos os arquivos encontrados em
/path/to/dir
.fonte
Outra opção seria usar apenas perl com a globstar.
A ativação
shopt -s globstar
em seu.bashrc
(ou em qualquer outro lugar) permite que o**
padrão global corresponda a todos os subdiretórios e arquivos de forma recursiva.Assim, o uso
perl -pXe 's/SEARCH/REPLACE/g' -i **
substituirá recursivamenteSEARCH
porREPLACE
.O
-X
sinalizador diz ao perl para "desativar todos os avisos" - o que significa que não se queixará de diretórios.O globstar também permite que você faça coisas como
sed -i 's/SEARCH/REPLACE/g' **/*.ext
se você queria substituirSEARCH
comREPLACE
em todos os arquivos da criança com a extensão.ext
.fonte
grep
esed
.