O comando a seguir está alterando corretamente o conteúdo de 2 arquivos.
sed -i 's/abc/xyz/g' xaa1 xab1
Mas o que preciso fazer é alterar vários desses arquivos dinamicamente e não sei os nomes dos arquivos. Quero escrever um comando que leia todos os arquivos do diretório atual, começando com xa*
e sed
deve alterar o conteúdo do arquivo.
sed -i 's/abc/xyz/g' xa*
?Respostas:
Melhor ainda:
porque ninguém sabe quantos arquivos existem e é fácil quebrar os limites da linha de comando.
Aqui está o que acontece quando há muitos arquivos:
fonte
for
comando. Para se proteger contra isso, você teria que usarfind ... | xargs ...
for
do que paraecho
ougrep
?"$i"
vez de$i
evitar a divisão de palavras nos nomes de arquivos com espaços. Caso contrário, isso é muito bom.for
faz parte da sintaxe da linguagem, nem mesmo um componente interno. Poissed -i 's/old/new' *
, a expansão de*
ALL deve ser passada como arglist para sed, e tenho certeza de que isso precisa acontecer antes que osed
processo possa ser iniciado. Usando ofor
loop, o arglist completo (a expansão de*
) nunca é passado como um comando, apenas armazenado na memória do shell e iterado. No entanto, não tenho nenhuma referência a isso, apenas parece provável que essa seja a diferença. (Eu adoraria ouvir de alguém mais entendido ...)Estou surpreso que ninguém tenha mencionado o argumento -exec a ser encontrado, destinado a esse tipo de caso de uso, embora ele inicie um processo para cada nome de arquivo correspondente:
Como alternativa, pode-se usar xargs, que invocará menos processos:
Ou, mais simplesmente, use a
+
variante exec em vez de;
em find para permitir que find forneça mais de um arquivo por chamada de subprocesso:fonte
find ./ -type f -name 'xa*' -exec sed -i '' 's/asd/dsg/g' {} \;
esse é o local para o comando find./
e um par de aspas simples-i
para o OSX../
é igual a.
e depois-i
possui apenas o parâmetro backupsuffix.-exec
opção de encontrar junto{} +
é suficiente para resolver o problema, conforme indicado, e deve ser adequada para a maioria dos requisitos. Masxargs
é uma escolha melhor em geral, porque também permite o processamento paralelo com a-p
opção. Quando sua expansão glob é grande o suficiente para exceder o comprimento da linha de comando, é provável que você também se beneficie de uma aceleração em uma execução sequencial.Você pode usar grep e sed juntos. Isso permite pesquisar subdiretórios recursivamente.
fonte
grep -v
para evitar pastas gitgrep -rl <old> . | grep -v \.git | xargs sed -i 's/<old>/<new>/g'
Esses comandos não funcionarão no padrão
sed
fornecido com o Mac OS X.De
man 1 sed
:Tentou
e
Ambos funcionam bem.
fonte
O @PaulR postou isso como um comentário, mas as pessoas devem vê-lo como uma resposta (e essa resposta funciona melhor para minhas necessidades):
Isso funcionará para uma quantidade moderada de arquivos, provavelmente da ordem de dezenas, mas provavelmente não da ordem de milhões .
fonte
sed -i 's|auth-user-pass nordvpn.txt|auth-user-pass /etc/openvpn/nordvpn.txt|g' *.ovpn
.Outra maneira mais versátil é usar
find
:fonte
Estou usando
find
para tarefa semelhante. É bem simples: você deve passá-lo como argumento para osed
seguinte:sed -i 's/EXPRESSION/REPLACEMENT/g' `find -name "FILE.REGEX"`
Dessa forma, você não precisa escrever loops complexos, e é simples ver quais arquivos você irá alterar, apenas execute
find
antes de executarsed
.fonte
você pode fazer
o texto ' xxxx ' u pesquisa e o substituirá por ' aaaa '
fonte
Se você é capaz de executar um script, aqui está o que eu fiz para uma situação semelhante:
Usando um dicionário / hashMap (matriz associativa) e variáveis para o
sed
comando, podemos percorrer a matriz para substituir várias seqüências. A inclusão de um curinga noname_pattern
arquivo permitirá substituir no local os arquivos por um padrão (isso pode ser algo comoname_pattern='File*.txt'
) em um diretório específico (source_dir
). Todas as alterações são gravadas nologfile
nodestin_dir
Primeiro, a matriz de pares é declarada, cada par é uma sequência de substituição e, em seguida,
WHAT1
será substituída porFOR1
eOTHER_string_to replace
será substituída porstring replaced
no arquivoFile.txt
. No loop, a matriz é lida, o primeiro membro do par é recuperado comoreplace_what=$i
e o segundo comoreplace_for=$j
. Ofind
comando pesquisa no diretório o nome do arquivo (que pode conter um curinga) e osed -i
comando substitui no (s) mesmo (s) arquivo (s) que foi definido anteriormente. Por fim, adicionei umgrep
redirecionado ao arquivo de log para registrar as alterações feitas nos arquivos.Isso funcionou para mim
GNU Bash 4.3
sed 4.2.2
e com base na resposta de VasyaNovikov para Loop sobre tuplas no bash .fonte