Encontre e substitua por sed no diretório e subdiretórios

244

Eu executo este comando para encontrar e substituir todas as ocorrências de 'apple' por 'orange' em todos os arquivos na raiz do meu site:

find ./ -exec sed -i 's/apple/orange/g' {} \;

Mas não passa por subdiretórios.

O que há de errado com este comando?

Aqui estão algumas linhas de saída de find ./:

./index.php
./header.php
./fpd
./fpd/font
./fpd/font/desktop.ini
./fpd/font/courier.php
./fpd/font/symbol.php
hd.
fonte
você poderia executar find ./e postar alguma saída de amostra? E a estrutura de diretórios, por favor. editar: obrigado!
27711 Jacob
Hum, sua descoberta está correta, funciona para mim com subdiretórios.
27411 Jacob
1
Como você sabe que ele não processa subdiretórios?
carlpett
porque fornece esses erros: sed: não foi possível editar ./fpd: não é um arquivo normal sed: não foi possível editar ./fpd/font: não é um arquivo regular sed: não foi possível editar ./fpd/font/makefont: não é uma regra
hd.
oh ... eu grep para apple e nada found.they todos foram substituídos. ;) obrigado . você abriu meus olhos !!!
hd.

Respostas:

421

Sua descoberta deve ser assim para evitar o envio de nomes de diretório para sed:

find ./ -type f -exec sed -i -e 's/apple/orange/g' {} \;
jfg956
fonte
19
Pode ser necessário alterar sed -i 's/apple/orange/g'para sed -i '' 's/apple/orange/g'para que isso funcione.
Paulmelnikow #
7
-iusa um argumento: a extensão usada para salvar o arquivo temporário. No GNU sed, parece que não há espaço entre eles -ie seu argumento, mas no BSD sed existe ... então o BSD -i '' 's/foo/bar/'é equivalente ao GNU -i 's/foo/bar/.
22414 Paulmelnikow
20
Na verdade, a adição -enão funciona no Mac OS. touch a b c d eseguido pelo comando acima produz uma listagem como esta: a a-e b b-e c c-e d d-e e e-e.
paulmelnikow
6
Para o Mac OS, isso responde stackoverflow.com/questions/19242275/… theRE error: illegal byte sequence
kakoma
3
Para usuários de casca de peixe, não se esqueça de citar os colchetes vazios '{}', porque o peixe expande automaticamente os colchetes vazios se não estiver entre aspas.
Kevin Cherepski
84

Para tarefas s & r maiores, é melhor e mais rápido usar grep e xargs, por exemplo;

grep -rl 'apples' /dir_to_search_under | xargs sed -i 's/apples/oranges/g'
Julius
fonte
20
Obrigado por esta resposta, foi muito útil! Se em um repositório git, é ainda mais rápido usandogit grep -l 'apples' | xargs sed -i 's/apples/oranges/g'
mrodrigues
4

Isso funcionou para mim:

find ./ -type f -exec sed -i '' 's#NEEDLE#REPLACEMENT#' *.php {} \;
blackdad
fonte
pergunta original não restringe a arquivos .php *, há também um uma ini
knocte
O não citado *.phpestá realmente incorreto; você teve sorte de não ter sido expandido no diretório inicial porque não havia nenhum arquivo correspondente lá.
Tripleee 21/07/19
3
grep -e apple your_site_root/**/*.* -s -l | xargs sed -i "" "s|apple|orage|"
rocLv
fonte
1

Como também existem pessoas do macOS lendo este (como eu fiz), o código a seguir funcionou para mim (na versão 10.14)

egrep -rl '<pattern>' <dir> | xargs -I@ sed -i '' 's/<arg1>/<arg2>/g' @

Todas as outras respostas usam -ie -enão funcionam no macOS.

Fonte

pat-s
fonte
0

Acho que podemos fazer isso com um comando simples de uma linha

for i in `grep -rl eth0 . 2> /dev/null`; do sed -i ‘s/eth0/eth1/’ $i; done

Consulte esta página .

Sukrant
fonte
-6

No linuxOS:

sed -i 's/textSerch/textReplace/g' namefile

se "sed" não funcionar, tente:

perl -i -pe 's/textSerch/textReplace/g' namefile
ฉัตร ชัย สิทธิ วง ค์
fonte
4
ele quer encontrar todos os arquivos em sub-diretórios contêm essa string e substituir, e não apenas um único arquivo
phuclv