Znajdź i zamień na sed w katalogu i podkatalogach

244

Uruchamiam to polecenie, aby znaleźć i zastąpić wszystkie wystąpienia „jabłka” słowem „pomarańczowy” we wszystkich plikach w katalogu głównym mojej witryny:

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

Ale nie przechodzi przez podkatalogi.

Co jest nie tak z tym poleceniem?

Oto kilka linii wyników find ./:

./index.php
./header.php
./fpd
./fpd/font
./fpd/font/desktop.ini
./fpd/font/courier.php
./fpd/font/symbol.php
hd.
źródło
czy możesz uruchomić find ./i opublikować przykładowe wyniki? I proszę o strukturę katalogów. edycja: dzięki!
Jacob
Hm, twoje znalezisko jest poprawne, działa dla mnie z podkatalogami.
Jacob
1
Skąd wiesz, że nie przetwarza podkatalogów?
carlpett
ponieważ daje następujące błędy: sed: nie można edytować ./fpd: nie jest to zwykły plik sed: nie można edytować ./fpd/font: nie jest zwykły plik sed: nie można edytować ./fpd/font/makefont: nie regula
hd.
och ... żałuję jabłka i nic nie znaleziono. wszystkie zostały zastąpione. ;) Dziękuję Ci . otworzyłeś mi oczy !!!
hd.

Odpowiedzi:

422

Twoje znalezisko powinno wyglądać tak, aby uniknąć wysyłania nazw katalogów do sed:

find ./ -type f -exec sed -i -e 's/apple/orange/g' {} \;
jfg956
źródło
19
Być może trzeba zmienić sed -i 's/apple/orange/g', aby sed -i '' 's/apple/orange/g'do tej pracy.
paulmelnikow
7
-iprzyjmuje argument: rozszerzenie użyte do zapisania pliku tymczasowego. W GNU sed wygląda na to, że nie ma między nimi spacji -i, ale w BSD sed jest… więc BSD -i '' 's/foo/bar/'jest równoważne z GNU -i 's/foo/bar/.
paulmelnikow
20
W rzeczywistości dodawanie -enie działa w systemie Mac OS. touch a b c d enastępnie powyżej polecenie tworzy katalog z listą tak: a a-e b b-e c c-e d d-e e e-e.
paulmelnikow
6
W przypadku systemu Mac OS to odpowiedzi stackoverflow.com/questions/19242275/... theRE error: illegal byte sequence
kakoma
3
W przypadku użytkowników skorupy ryb pamiętaj o cytowaniu pustych nawiasów klamrowych '{}', ponieważ ryba automatycznie rozszerza puste nawiasy klamrowe, jeśli nie są cytowane.
Kevin Cherepski,
84

W przypadku większych zadań s & r lepiej i szybciej jest używać grep i xargs, więc na przykład;

grep -rl 'apples' /dir_to_search_under | xargs sed -i 's/apples/oranges/g'
Juliusz
źródło
20
Dzięki za tę odpowiedź, była bardzo pomocna! W repozytorium git korzystanie z niego jest jeszcze szybszegit grep -l 'apples' | xargs sed -i 's/apples/oranges/g'
mrodrigues,
4

To działało dla mnie:

find ./ -type f -exec sed -i '' 's#NEEDLE#REPLACEMENT#' *.php {} \;
blackdad
źródło
oryginalne pytanie nie ogranicza się do plików * .php, jest też jeden .ini
knocte
Cudzysłowy *.phpjest naprawdę niepoprawny; po prostu miałeś szczęście, że nie został rozwinięty w katalogu startowym, ponieważ nie było tam żadnych pasujących plików.
tripleee
3
grep -e apple your_site_root/**/*.* -s -l | xargs sed -i "" "s|apple|orage|"
rocLv
źródło
1

Ponieważ są też ludzie macOS czytający ten (tak jak ja), poniższy kod działał dla mnie (10.14)

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

Wszystkie pozostałe odpowiedzi używają -ii -enie działają w systemie macOS.

Źródło

pat-s
źródło
0

Myślę, że możemy to zrobić za pomocą prostej linii w jednym wierszu

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

Sprawdź tę stronę .

Sukrant
źródło
-6

W systemie Linux:

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

jeśli „sed” nie działa spróbuj:

perl -i -pe 's/textSerch/textReplace/g' namefile
ฉัตร ชัย สิทธิ วง ค์
źródło
4
chce znaleźć wszystkie pliki w podkatalogach zawierające ten ciąg i zastąpić nie tylko jeden plik
phuclv