Preciso substituir uma string em muitos arquivos em uma pasta, apenas com ssh
acesso ao servidor. Como posso fazer isso?
461
cd /path/to/your/folder
sed -i 's/foo/bar/g' *
Ocorrências de "foo" serão substituídas por "bar".
Em sistemas BSD como o macOS, você precisa fornecer uma extensão de backup como -i '.bak'
"risco de corrupção ou conteúdo parcial" por página de manual.
cd /path/to/your/folder
sed -i '.bak' 's/foo/bar/g' *
sed
,-i
requer uma sequência após ela, que é anexada aos nomes de arquivos antigos. Então,sed -i .bak 's/foo/bar/g' *.xx
move todos os.xx
arquivos para o.xx.bak
nome equivalente e gera os.xx
arquivos com a substituição foo → bar.sed -i 's/foo\ with\ spaces/bar/g' *
. Suponho que você tenha descoberto depois de tanto tempo ... mas dessa forma fica para outras pessoas que encontram o mesmo problema.sed -i -e 's/foo/bar/g' $(find /home/user/base/dir)
Semelhante à resposta de Kaspar, mas com o sinalizador g para substituir todas as ocorrências em uma linha.
Para caso global insensitivo:
fonte
LC_ALL=C find ./ -type f -exec sed -i '' -e 's/proc.priv/priv/g' {} \;
(ver este post e este )--include=*.whatever
com -r.git/
. Certifique-se decd
descer para um nível mais baixo.git status
retorna:error: bad index file sha1 signature.... fatal: index file corrupt
. O que da?A resposta do @ kev é boa, mas afeta apenas os arquivos no diretório imediato. O exemplo abaixo usa grep para localizar arquivos recursivamente. Funciona para mim sempre.
Divisão de comando
grep -r : --recursive , leia recursivamente todos os arquivos em cada diretório.
grep -l : --print-with-fósforos , imprime o nome de cada arquivo que possui uma correspondência, em vez de imprimir linhas correspondentes.
grep -i : --ignore-case .
xargs : transforme o STDIN em argumentos, siga esta resposta .
O comando xargs -i @ ~ contém @ ~ : um espaço reservado para o argumento a ser usado em uma posição específica no ~ command ~ , o sinal @ é um espaço reservado que pode ser substituído por qualquer string.
sed -i : edita arquivos no local, sem backups.
sed s / regexp / Replacement / : substitui a sequência correspondente de regexp pela substituição .
sed s / regexp / replace / g : global , faça a substituição para cada partida em vez de apenas a primeira partida.
fonte
grep --include={*.php,*.html,*.js} -rnl './' -e "old-word" | xargs -i@ sed -i 's/old-word/new-word/g' @
|
, também, por que-i
no comando xargs? Eu li no manual que está obsoleto e deve usá-lo-I
. E é@
usado como um delimitador para início e fim para padrão?grep -rli 'old-word' * | xargs -I@ sed -i '' 's/2.0.0/latest/g' @
rli
) e do@
sinal, por exemploIsso funcionou para mim:
Howerver, este não fez:
sed -i 's/string1/string2/g' *
. Talvez "foo" não tenha sido string1 e "bar" não string2.fonte
find ./ -type f -exec sed -i '' -e 's/string1/string2/' {} \;
Existem algumas respostas padrão para isso já listadas. Geralmente, você pode usar o find para listar recursivamente os arquivos e depois executar as operações com sed ou perl .
Para usos mais rápidos, você pode achar que o comando rpl é muito mais fácil de lembrar. Aqui está a substituição (foo -> bar), recursivamente em todos os arquivos:
rpl -R foo bar .
Você provavelmente precisará instalá-lo (
apt-get install rpl
ou similar).No entanto, para trabalhos mais difíceis que envolvem expressões regulares e substituição reversa ou renomeação de arquivos, além de pesquisar e substituir, a ferramenta mais geral e poderosa de que conheço é a repren , um pequeno script Python que escrevi há algum tempo. tarefas de renomeação e refatoração mais espinhosas. Os motivos pelos quais você pode preferir são:
Para usá-lo
pip install repren
. Verifique o README para exemplos.fonte
Para substituir uma sequência em vários arquivos, você pode usar:
Por exemplo
Blog de origem
fonte
Para substituir um caminho nos arquivos (evitando caracteres de escape), você pode usar o seguinte comando:
O sinal @ significa que todos os caracteres especiais devem ser ignorados na seguinte sequência.
fonte
Caso sua string tenha uma barra (/), você poderá alterar o delimitador para '+'.
Este comando seria executado recursivamente no diretório atual.
fonte
../domain.com
paradomain.com
As ocorrências da primeira linha de "foo" serão substituídas por "bar". E você pode usar a segunda linha para verificar.
fonte
grep -rl 'foo' . | xargs sed -i 's/foo/bar/g'
Se você tiver uma lista de arquivos, poderá usar
Se você tiver todos os arquivos, poderá usar
Se você tiver uma lista de arquivos com extensão, poderá usar
fonte
replace "old_string" "new_string" -- *.txt
replace
utilitário. Sem essas informações, essa resposta está incompleta."Você também pode usar o find e o sed, mas acho que essa pequena linha de perl funciona bem.
"(Extraído de http://www.liamdelahunty.com/tips/linux_search_and_replace_multiple_files.php )
Meus melhores resultados vêm do uso de perl e grep (para garantir que o arquivo tenha a expressão de pesquisa)
fonte
Como você deseja procurar a sequência
search
e substituí-lareplace
por vários arquivos, esta é minha fórmula de uma linha testada em batalha :Explicação rápida do grep:
-R
- pesquisa recursiva-i
- não diferencia maiúsculas de minúsculas-I
- pule arquivos binários (você quer texto, certo?)-l
- imprima uma lista simples como saída. Necessário para os outros comandosA saída grep é então canalizada para sed (através de xargs), que é usada para substituir o texto. A
-i
bandeira alterará o arquivo diretamente. Remova-o para uma espécie de modo "funcionamento a seco".fonte
Eu inventei minha própria solução antes de encontrar esta pergunta (e respostas). Procurei por diferentes combinações de "substituir" "vários" e "xml", porque esse era meu aplicativo, mas não encontrei esse em particular.
Meu problema: tive arquivos xml de primavera com dados para casos de teste, contendo objetos complexos. Um refator no código-fonte java alterou muitas classes e não se aplicava aos arquivos de dados xml. Para salvar os dados dos casos de teste, eu precisava alterar todos os nomes de classe em todos os arquivos xml, distribuídos em vários diretórios. Tudo isso enquanto salvava cópias de segurança dos arquivos xml originais (embora isso não fosse obrigatório, pois o controle de versão me salvaria aqui).
Eu estava procurando por uma combinação de
find
+sed
, porque funcionou para mim em outras situações, mas não com várias substituições ao mesmo tempo.Então eu encontrei a resposta ask ubuntu e isso me ajudou a construir minha linha de comando:
E funcionou perfeitamente (bem, meu caso teve seis substituições diferentes). Mas observe que ele tocará em todos os arquivos * .xml no diretório atual. Por esse motivo, e se você é responsável por um sistema de controle de versão, convém filtrar primeiro e transmitir apenas aos
sed
que realmente possuem as strings que deseja; gostar:fonte
findstr /spin /c:"quéquieresbuscar" *.xml
será útil.fonte
Realmente idiota, mas não consegui que nenhum dos comandos sed funcionasse corretamente no OSX, então fiz essa coisa idiota:
^ - copie essas três linhas na minha área de transferência (sim, inclua a nova linha final) e, em seguida:
vi *
e mantenha pressionado o comando-v até que não exista nenhum arquivo.
Burro ... hacky ... eficaz ...
fonte
Em um MacBook Pro, usei o seguinte (inspirado em https://stackoverflow.com/a/19457213/6169225 ):
fonte
-e
apenas diz ao sed que o próximo token é um comando. Para expressões regulares estendidas, use em seu-E
lugar.O editor de fluxo modifica vários arquivos "no local" quando chamado com o
-i
comutador, o que leva um arquivo de backup que termina como argumento. assimsubstitui
foo
porbar
todos os arquivos nesta pasta, mas não desce em subpastas. No entanto, isso irá gerar um novo.bak
arquivo para cada arquivo no seu diretório. Para fazer isso recursivamente para todos os arquivos neste diretório e todos os seus subdiretórios, você precisa de um ajudante, comofind
, para percorrer a árvore de diretórios.find
permite restrições adicionais sobre quais arquivos modificar, especificando outros argumentos comofind ./ -name '*.php' -or -name '*.html' -print0
, se necessário.Nota: O GNU
sed
não requer um final de arquivo,sed -i 's/foo/bar/g' *
também funcionará; O FreeBSDsed
exige uma extensão, mas permite um espaço intermediário, assimsed -i .bak s/foo/bar/g *
funciona.fonte
script para comando multiedit
Com a resposta de Kaspar, criei um script bash para aceitar argumentos da linha de comando e, opcionalmente, limitar os nomes de arquivos correspondentes a um padrão. Salve no seu $ PATH e torne o executável; em seguida, basta usar o comando acima.
Aqui está o script:
fonte
Se o arquivo contiver barras invertidas (caminhos geralmente), você pode tentar algo como isto:
ex:
fonte
Para manter meu nó pessoal em inglês, escrevi um script utilitário que ajuda a substituir vários pares de strings novos / antigos por todos os arquivos em um diretório recursivamente.
O par múltiplo de cadeia antiga / nova é gerenciado em um mapa de hash.
O diretório pode ser definido via linha de comando ou variável de ambiente, o mapa é codificado no script, mas você pode modificar o código para carregar de um arquivo, se necessário.
Requer bash 4.2, devido a algum novo recurso.
en_standardize.sh:
fonte
Usar o comando ack seria muito mais rápido assim:
Além disso, se você tiver um espaço em branco no resultado da pesquisa. Você precisa escapar disso.
fonte
Estou dando um exemplo para corrigir um erro shebang comum em fontes python.
Você pode tentar a abordagem grep / sed. Aqui está um que funciona com o GNU sed e não quebra um repositório git:
Ou você pode usar greptile :)
Acabei de testar o primeiro script e o segundo também deve funcionar. Tenha cuidado com os caracteres de escape, acho que deve ser mais fácil usar o greptile na maioria dos casos. Obviamente, você pode fazer muitas coisas interessantes com o sed e, para isso, pode ser preferível dominar o uso com o xargs.
fonte
Encontrei este em outro post (não me lembro qual) e, embora não seja o mais elegante, é simples e, como um usuário iniciante do Linux, não me deu problemas
se você tiver espaços ou outros caracteres especiais, use a \
para cadeias de caracteres nos subdiretórios use **
fonte
O comando abaixo pode ser usado para pesquisar primeiro os arquivos e substituí-los:
Por exemplo
fonte
Há uma maneira mais fácil usando um arquivo de script simples:
abra o arquivo no gedit ou em um editor de sua escolha, eu uso o gedit aqui.
Em seguida, no editor, cole o seguinte no arquivo
Salve o arquivo, feche o gedit , saia do terminal ou simplesmente feche-o e inicie-o para poder carregar o novo script que você adicionou.
Navegue para o diretório em que você tem vários arquivos que deseja editar. Então corra:
Pressione enter e isso substituirá automaticamente a cadeia antiga e a cadeia antiga1 em todos os arquivos que as contêm pela nova cadeia e nova cadeia1 respectivamente.
Irá pular todos os diretórios e arquivos que não contêm as strings antigas.
Isso pode ajudar a eliminar o trabalho tedioso de digitar, caso você tenha vários diretórios com arquivos que precisam ser substituídos. Tudo o que você precisa fazer é navegar para cada um desses diretórios e executar:
#replace_string_files_present_dir
Tudo o que você precisa fazer é garantir que você incluiu ou adicionou todas as seqüências de substituição, como mostrei acima:
replace "oldstring" "newstring" -- *
no final do arquivo / bin / replace_string_files_present_dir .
Para adicionar uma nova string de substituição, basta abrir o script que criamos, digitando o seguinte no terminal:
sudo gedit /bin/replace_string_files_present_dir
Não se preocupe com o número de strings de substituição adicionadas, elas não terão efeito se a string antiga não for encontrada.
fonte
.gitlab-ci.yml
ou atravis.yml
). Cada turno que consiste em escrever um script para executá-lo mais tarde é um anti-padrão, pois você precisará criar um script para a criação do script (e eu fico confuso, na maioria das vezes)$ substitua "De" "Para" - `find / path / to / folder -type f`
(replace - um utilitário de substituição de string do MySQL Database System)
fonte