Jak wykonać rekurencyjne znajdowanie / zamianę ciągu na awk lub sed?

675

Jak znaleźć i wymienić każde wystąpienie:

subdomainA.example.com

z

subdomainB.example.com

w każdym pliku tekstowym w /home/www/drzewie katalogów rekurencyjnie?

Tedd
źródło
93
Wskazówka: Nie wykonuj poniższych czynności w drzewie kasy SVN ... spowoduje to zastąpienie magicznych plików folderów .svn.
J. Polfer,
7
o mój boże, właśnie to właśnie zrobiłem. Ale zadziałało i nie wyrządziło żadnej szkody. Co najgorszego może się zdarzyć?
J. Katzwinkel,
5
@ J.Katzwinkel: przynajmniej może uszkodzić sumy kontrolne, co może uszkodzić twoje repozytorium.
ninjagecko
3
Szybka wskazówka dla wszystkich osób używających sed: doda nowe końcowe wiersze do twoich plików. Jeśli ich nie chcesz, najpierw wykonaj polecenie zamiany znalezienia, które nie pasuje do niczego, i zatwierdź to w git. Więc zrób prawdziwy. Następnie uruchom bazę interaktywnie i usuń pierwszy.
funroll
5
Można wykluczyć katalog, takich jak git, z wynikami stosując -path ./.git -prune -osię find . -path ./.git -prune -o -type f -name '*matchThisText*' -print0przed potokiem do xargs
devinbost

Odpowiedzi:

850
find /home/www \( -type d -name .git -prune \) -o -type f -print0 | xargs -0 sed -i 's/subdomainA\.example\.com/subdomainB.example.com/g'

-print0każe findwydrukować każdy wynik oddzielony znakiem null, a nie nowym wierszem. W mało prawdopodobnym przypadku, gdy katalog zawiera pliki z nowymi liniami w nazwach, nadal pozwala to xargsna pracę z poprawnymi nazwami plików.

\( -type d -name .git -prune \)jest wyrażeniem, które całkowicie pomija wszystkie nazwane katalogi .git. Możesz łatwo go rozwinąć, jeśli używasz SVN lub masz inne foldery, które chcesz zachować - po prostu dopasuj do większej liczby nazw. Jest mniej więcej równoważny -not -path .git, ale bardziej wydajny, ponieważ zamiast sprawdzać każdy plik w katalogu, pomija go całkowicie. Jest -oto wymagane ze względu na to, jak -prunefaktycznie działa.

Aby uzyskać więcej informacji, zobacz man find.

wilczomlecz
źródło
132
W OSX może wystąpić sed: 1: "...": invalid command code .problem. Wygląda na to, że opcja -i oczekuje rozszerzenia i analizuje 's/../...'polecenie. Rozwiązanie: przekaż rozszerzenie '' na opcję -i jak sed -i '' 's/....
Robert Lujo,
6
Uwaga: jeśli używasz tego w katalogu i zastanawiasz się, dlaczego svn stnie pokazuje żadnych zmian, dzieje się tak dlatego, że zmodyfikowałeś również pliki w katalogach .svn! Użyj find . -maxdepth 1 -type f -print0 | xargs -0 sed -i 's/toreplace/replaced/g'zamiast tego.
ACK_stoverflow 26.09.13
57
Uważaj też, jeśli korzystasz z repozytorium git. Myślałem, że jestem mądry, testując to na wyraźnej gałęzi, aby móc cofnąć się, jeśli zrobiłoby to coś złego, ale zamiast tego uszkodził mój indeks git.
Ciryon
13
Użyj tego, grep -r 'hello' -l --null . | xargs -0 sed -i 's#hello#world#g'aby uniknąć edycji niepowiązanych plików (sed może zmienić kodowanie plików).
caiguanhao
6
„ale zamiast tego zepsułem mój indeks git.” Nie przejmuj się zbytnio tym, co możesz zrobić, find .git ... | ... 'sed -i s/(the opposite from before)/g'aby naprawić indeks git
Massey101
259

Uwaga : Nie uruchamiaj tego polecenia w folderze zawierającym repozytorium git - zmiany na .git mogą uszkodzić indeks git.

find /home/www/ -type f -exec \
    sed -i 's/subdomainA\.example\.com/subdomainB.example.com/g' {} +

W porównaniu do innych odpowiedzi tutaj jest to prostsze niż większość i używa sed zamiast perla, o co zadawano oryginalne pytanie.

John Zwinck
źródło
50
Pamiętaj, że jeśli korzystasz z BSD sed (w tym na Mac OS X), musisz podać jawnie pusty ciąg argumentu -iopcji sed . tj .: sed -i '' 's/original/replacement/g'
Nathan Craike
2
@JohnZwinck Mój błąd, brakowało +. O dziwo, rozwiązanie Nikity działa dla mnie szybciej.
Sam
6
@AoeAoe: +Znacznie zmniejsza liczbę spawnowanych sedprocesów. Jest bardziej wydajny.
John Zwinck
4
Jak mogę to bezpiecznie zrobić w folderze z repozytorium git?
Hatszepsut
20
Jest to bezpieczne, aby wykonać na folderze zawierającym git repo jeśli wykluczyć repo z wyników znajdują się: find . -not -path '*/\.git*' -type f ....
Dale Anderson
210

Najprostszym sposobem jest dla mnie

grep -rl oldtext . | xargs sed -i 's/oldtext/newtext/g'
Anatolij
źródło
1
@Anatoly: tylko jedno pytanie: jak mogę wykluczyć pliki binarne (pliki wykonywalne) ?
user2284570,
3
@ user2284570 Użyj flag -Ilub --binary-file=without-matchgrep.
Zéychin
34
Działa to szczególnie dobrze, gdy trzeba wykluczyć katalogi, jak w przypadku .svn. Na przykład:grep -rl oldtext . --exclude-dir=.svn | xargs sed -i 's/oldtext/newtext/g'
phyatt
11
brew install gnu-sedi używaj gsedw OSX, aby uniknąć bólu.
P i
1
Chłopaki proszę uwagę, jeśli projekt jest git wersji, użyj zamiast tego: git grep -rl oldtext . | xargs sed -i 's/oldtext/newtext/g'. w ogóle nie fajnie jest pierdolić swój .gitkatalog
Paolo
61

Wszystkie triki są prawie takie same, ale podoba mi się ten:

find <mydir> -type f -exec sed -i 's/<string1>/<string2>/g' {} +
  • find <mydir>: wyszukaj w katalogu.

  • -type f:

    Plik jest typu: zwykły plik

  • -exec command {} +:

    Ten wariant akcji -exec uruchamia określone polecenie na wybranych plikach, ale linia poleceń jest budowana przez dołączenie każdej wybranej nazwy pliku na końcu; całkowita liczba wywołań polecenia będzie znacznie mniejsza niż liczba dopasowanych plików. Wiersz poleceń jest budowany w taki sam sposób, jak xargs buduje wiersze poleceń. W poleceniu dozwolona jest tylko jedna instancja „{}”. Polecenie jest wykonywane w katalogu startowym.

I159
źródło
@ user2284570 z opcją -exec? Spróbuj ustawić ścieżkę do pliku wykonywalnego zamiast nazwy narzędzia.
I159
@ I159: Nie: wyklucz pliki wykonywalne (ale dołącz skrypty powłoki) .
user2284570,
8
@ I159 Czy ta odpowiedź nie jest identyczna z odpowiedzią Johna Zwincka ?
Przywróć Monikę, proszę,
1
@ user2284570 Pojęcie „pliku binarnego” nie jest całkowicie dobrze zdefiniowane. Możesz użyć filepolecenia, aby spróbować określić typ każdego pliku, ale przypadkowe zmiany w jego wyniku mogą być nieco oszałamiające. Opcja -I(aka --mime) nieco pomaga lub --mime-typejeśli masz taką opcję . Jak dokładnie przeformułować ten schludny jednowierszowy, aby to zrobić, niestety nie wchodzi w zakres tego małego pola komentarza. Może opublikujesz osobne pytanie, jeśli potrzebujesz pomocy? (Być może zatem dodaj tutaj komentarz z linkiem.)
tripleee
1
najczystsza odpowiedź! dzięki kolego
jukerok
39
cd /home/www && find . -type f -print0 |
  xargs -0 perl -i.bak -pe 's/subdomainA\.example\.com/subdomainB.example.com/g'
Zatrudniony rosyjski
źródło
2
Jestem ciekaw, czy istnieje powód, aby użyć -print0i xargszamiast -execlub -execdir?
Philipp
4
Jest: z „man find”: Określone polecenie jest uruchamiane raz dla każdego dopasowanego pliku. Oznacza to, że jeśli w katalogu / home / www znajduje się 2000 plików, wówczas „find ... -exec ...” spowoduje 2000 wywołań perla; podczas gdy „znajdź ... | xargs ... 'wywoła perla tylko raz lub dwa razy (przy założeniu ARG_MAX o wielkości około 32 KB i średniej długości nazwy pliku wynoszącej 20).
Zatrudniony rosyjski
2
@Employed Russian: dlatego użyjesz find -exec command {} +- pozwala uniknąć nadmiernego wywoływania polecenia, takiego jak xargs, ale bez osobnego procesu.
John Zwinck,
2
Na jakiej platformie? Rozwiązanie xargs jest przenośne, „magiczne” wywołania „find ... -exec”, które nie wywołują podprocesu dla każdego znalezionego pliku, nie są.
Zatrudniony rosyjski
4
@EmployedRussian, find -exec ... {} +został określony przez POSIX od 2006 roku.
Charles Duffy
34

Dla mnie najłatwiejszym rozwiązaniem do zapamiętania jest https://stackoverflow.com/a/2113224/565525 , tj .:

sed -i '' -e 's/subdomainA/subdomainB/g' $(find /home/www/ -type f)

UWAGA : -i ''rozwiązuje problem OSXsed: 1: "...": invalid command code .

UWAGA : Jeśli jest zbyt wiele plików do przetworzenia, otrzymasz Argument list too long. Obejście - zastosowanie find -execlub xargsrozwiązanie opisane powyżej.

Robert Lujo
źródło
4
workaroundPowinna być preferowana składnia we wszystkich przypadkach.
Przywróć Monikę, proszę,
1
Problem z zastępowaniem poleceń $(find...)polega na tym, że powłoka nie ma możliwości obsługi nazw plików z białymi spacjami lub innymi metaznakami powłoki. Jeśli wiesz, że to nie jest problem, to podejście jest w porządku; ale mamy zbyt wiele pytań, w których ludzie nie byli ostrzegani o tym problemie lub nie rozumieli ostrzeżenia.
tripleee
30

Dla każdego, kto korzysta ze srebrnego wyszukiwarki ( ag)

ag SearchString -l0 | xargs -0 sed -i 's/SearchString/Replacement/g'

Ponieważ ag domyślnie ignoruje pliki / foldery git / hg / svn, uruchomienie w repozytorium jest bezpieczne.

Jacob Wang
źródło
16

Jeden miły oneliner jako dodatek. Używanie git grep.

git grep -lz 'subdomainA.example.com' | xargs -0 perl -i'' -pE "s/subdomainA.example.com/subdomainB.example.com/g"
Jimmy Kane
źródło
3
Dobry pomysł, jeśli pracujesz w repozytorium git, ponieważ nie ryzykujesz nadpisania .git / content (jak podano w komentarzach do innej odpowiedzi).
mahemoff
1
Dzięki, używam go jako funkcji bash refactor() { echo "Replacing $1 by $2 in all files in this git repository." git grep -lz $1| xargs -0 perl -i'' -pE "s/$1/$2/g" }Użycie, na przykład do zastąpienia słowa „słowem” słowem „miecz”: refactor word swordnastępnie sprawdź, co to zrobiło git diff.
Paul Rougieux,
16

Aby ograniczyć rekursywnie pliki sed, możesz grepdla instancji ciągu:

grep -rl <oldstring> /path/to/folder | xargs sed -i s^<oldstring>^<newstring>^g

Jeśli uruchomisz man grep, zauważysz, że możesz również zdefiniować --exlude-dir="*.git"flagę, jeśli chcesz pominąć przeszukiwanie katalogów .git, unikając problemów z indeksem git, jak inni uprzejmie zauważyli.

Prowadzi Cię do:

grep -rl --exclude-dir="*.git" <oldstring> /path/to/folder | xargs sed -i s^<oldstring>^<newstring>^g
domdambrogia
źródło
13

Ten jest kompatybilny z repozytoriami git i nieco prostszy:

Linux:

git grep -l 'original_text' | xargs sed -i 's/original_text/new_text/g'

Prochowiec:

git grep -l 'original_text' | xargs sed -i '' -e 's/original_text/new_text/g'

(Dzięki http://blog.jasonmeridth.com/posts/use-git-grep-to-replace-strings-in-files-in-your-git-repository/ )

seddonym
źródło
Rozsądniej użyć git-grep„s -zopcję razem z xargs -0.
gniourf_gniourf
git grepoczywiście ma to sens tylko w przypadku gitrepo. Ogólny zamiennik byłby grep -r.
tripleee
@gniourf_gniourf Czy potrafisz wyjaśnić?
Petr Peller
2
@PetrPeller: z -z, git-grepoddzieli pola wyjściowe bajtami pustymi zamiast znaków nowej linii; i with -0, xargsodczyta dane wejściowe oddzielone pustymi bajtami zamiast pustych znaków (i nie rób dziwnych rzeczy z cudzysłowami). Więc jeśli nie chcesz polecenie złamać jeśli nazwy plików zawierają spacje, cytaty lub inne znaki śmieszne, polecenie to: git grep -z -l 'original_text' | xargs -0 sed ....
gniourf_gniourf
10
find /home/www/ -type f -exec perl -i.bak -pe 's/subdomainA\.example\.com/subdomainB.example.com/g' {} +

find /home/www/ -type f wyświetli listę wszystkich plików w / home / www / (i jego podkatalogach). Flaga „-exec” informuje find, aby uruchomić następującą komendę dla każdego znalezionego pliku.

perl -i.bak -pe 's/subdomainA\.example\.com/subdomainB.example.com/g' {} +

to polecenie uruchamiane na plikach (wiele na raz). Zostanie {}zastąpiony przez nazwy plików. Na +końcu polecenia mówi findo zbudowaniu jednego polecenia dla wielu nazw plików.

Per find stronie : „Linia poleceń jest budowana w taki sam sposób, jak xargs buduje swoje linie poleceń”.

W ten sposób można osiągnąć swój cel (i obsługiwać nazwy plików zawierające spacje) bez użycia xargs -0lub -print0.

unutbu
źródło
8

Właśnie tego potrzebowałem i nie byłem zadowolony z szybkości dostępnych przykładów. Więc wymyśliłem własne:

cd /var/www && ack-grep -l --print0 subdomainA.example.com | xargs -0 perl -i.bak -pe 's/subdomainA\.example\.com/subdomainB.example.com/g'

Ack-grep jest bardzo wydajny w wyszukiwaniu odpowiednich plików. To polecenie zastąpiło ~ 145 000 plików, a inne zajęły tak długo, że nie mogłem się doczekać ich zakończenia.

Henno
źródło
Fajnie, ale grep -ril 'subdomainA' *nie jest tak szybki jak grep -Hr 'subdomainA' * | cut -d: -f1.
trusktr
@Henno: tylko jedno pytanie: jak mogę wykluczyć pliki binarne (pliki wykonywalne) ?
user2284570,
ack-grep robi to automatycznie dla ciebie.
Henno
@Henno: Czy zawiera skrypty powłoki?
user2284570,
Tak. Powyżej znajduje się pełna lista typów plików wspiera: beyondgrep.com/documentation
Henno
6

Prosta metoda, jeśli chcesz wykluczyć katalogi ( --exclude-dir=.svn), a także może mieć nazwy plików ze spacjami (używając 0Byte z grep -Zixargs -0

grep -rlZ oldtext . --exclude-dir=.svn | xargs -0 sed -i 's/oldtext/newtext/g'
fantom
źródło
6

Najprostszy sposób na zamianę ( wszystkie pliki, katalog, rekurencyjne )

find . -type f -not -path '*/\.*' -exec sed -i 's/foo/bar/g' {} +

Uwaga: Czasami może być konieczne zignorowanie niektórych ukrytych plików, np. .gitMożesz użyć powyższej komendy.

Jeśli chcesz dołączyć ukryte pliki,

find . -type f  -exec sed -i 's/foo/bar/g' {} +

W obu przypadkach ciąg foozostanie zastąpiony nowym ciągiembar

Sazzad Hissain Khan
źródło
5

grep -lr 'subdomainA.example.com' | while read file; do sed -i "s/subdomainA.example.com/subdomainB.example.com/g" "$file"; done

Wydaje mi się, że większość ludzi nie wie, że mogą przesłać coś do „podczas odczytu pliku” i pozwala to uniknąć tych nieprzyjemnych argumentów -print0, jednocześnie zachowując spacje w nazwach plików.

Dalsze dodawanie echoprzed sedem pozwala zobaczyć, jakie pliki zmienią się przed wykonaniem tego.

MadMan2064
źródło
Powód -print0jest przydatny, ponieważ obsługuje przypadki, które while readpo prostu nie są w stanie obsłużyć - nowa linia jest poprawnym znakiem w nazwie pliku uniksowego, więc aby kod był całkowicie niezawodny, musi również radzić sobie z takimi nazwami plików. (Ponadto, chcesz read -runiknąć niektórych read
przykrych
Ponadto sedjest to brak opcji, jeśli nie ma żadnych dopasowań, więc grepnie jest to naprawdę konieczne; chociaż jest to przydatna optymalizacja, aby uniknąć przepisywania plików, które nie zawierają żadnych dopasowań, jeśli masz ich wiele lub chcesz niepotrzebnie aktualizować znaczniki daty na plikach.
tripleee
5

Możesz użyć awk, aby rozwiązać ten problem, jak poniżej,

for file in `find /home/www -type f`
do
   awk '{gsub(/subdomainA.example.com/,"subdomainB.example.com"); print $0;}' $file > ./tempFile && mv ./tempFile $file;
done

mam nadzieję, że ci to pomoże !!!

sarath kumar
źródło
Działa na MacO bez żadnych problemów! Wszystkie sedpolecenia bazowe nie powiodły się, gdy pliki binarne zostały uwzględnione, nawet przy specyficznych ustawieniach systemu OSX.
Jankapunkt
Ostrożnie ... to wybuchnie, jeśli którykolwiek ze findzwrotów plików będzie miał spację w swoich nazwach! Jest o wiele bezpieczniejszy w użyciu while read: stackoverflow.com/a/9612560/1938956
Soren Bjornstad
4

Spróbuj tego:

sed -i 's/subdomainA/subdomainB/g' `grep -ril 'subdomainA' *`
RikHic
źródło
1
Cześć @RikHic, fajna wskazówka - myślałem o czymś takim; niestety, powyższe formatowanie nie wyszło dobrze :) Więc spróbuję z tagiem wstępnym (nie działa) - więc z uciekającymi się backtickami: sed -i 's/subdomainA/subdomainB/g'` grep -ril 'subdomainA' /home/www/*` - To wciąż nie wygląda zbyt dobrze, ale powinno przetrwać copypaste :) Pozdrawiam!
sdaau,
4
#!/usr/local/bin/bash -x

find * /home/www -type f | while read files
do

sedtest=$(sed -n '/^/,/$/p' "${files}" | sed -n '/subdomainA/p')

    if [ "${sedtest}" ]
    then
    sed s'/subdomainA/subdomainB/'g "${files}" > "${files}".tmp
    mv "${files}".tmp "${files}"
    fi

done
petrus4
źródło
4

Zgodnie z tym postem na blogu:

find . -type f | xargs perl -pi -e 's/oldtext/newtext/g;'
J.Hpour
źródło
Jak uciekasz przed ukośnikami /? Na przykład chcę zastąpić adresy IP: xxx.xxx.xxx.xxxforxxx.xxx.xxx.xxx/folder
Pathros
Możesz uciec /z \. Na przykład:find . -type f | xargs perl -pi -e 's/xxx.xxx.xxx.xxx\/folder/newtext/g;'
J.Hpour
3

Jeśli nie masz nic przeciwko używaniu vimrazem z narzędziami greplub findnarzędziami, możesz śledzić odpowiedź udzieloną przez użytkownika Gert w tym linku -> Jak zamienić tekst w hierarchii dużych folderów? .

Oto oferta:

  • rekurencyjnie grep dla ciągu, który chcesz zastąpić w określonej ścieżce, i weź tylko pełną ścieżkę pasującego pliku. (to by było $(grep 'string' 'pathname' -Rl).

  • (opcjonalnie) jeśli chcesz wykonać kopię zapasową tych plików w scentralizowanym katalogu, możesz użyć tego również: cp -iv $(grep 'string' 'pathname' -Rl) 'centralized-directory-pathname'

  • po tym możesz dowolnie edytować / zamieniać według vimschematu podobnego do tego podanego na podanym linku:

    • :bufdo %s#string#replacement#gc | update
mzcl-mn
źródło
2

Trochę starej szkoły, ale działało to na OS X.

Jest kilka trików:

• Będzie edytować tylko pliki z rozszerzeniem .slsw bieżącym katalogu

.należy uciec, aby upewnić się, sedże nie ocenia ich jako „żadnej postaci”

,jest używany jako sedseparator zamiast zwykłego/

Pamiętaj też, że jest to edycja szablonu Jinja, aby przekazać variableścieżkę import(ale to nie jest temat).

Najpierw sprawdź, czy polecenie sed robi to, co chcesz (spowoduje to wydrukowanie zmian tylko na standardowe wyjście, nie spowoduje to zmiany plików):

for file in $(find . -name *.sls -type f); do echo -e "\n$file: "; sed 's,foo\.bar,foo/bar/\"+baz+\"/,g' $file; done

W razie potrzeby edytuj polecenie sed, gdy będziesz gotowy do wprowadzenia zmian:

for file in $(find . -name *.sls -type f); do echo -e "\n$file: "; sed -i '' 's,foo\.bar,foo/bar/\"+baz+\"/,g' $file; done

Zauważ, że -i ''w sed polecenia, nie chcę, aby utworzyć kopię zapasową oryginalnych plików (jak wyjaśniono w w miejscu edycji z sed na OSX lub w komentarzu Roberta LUJO w tej stronie).

Szczęśliwi ludzie z sedingu!

Raphvanns
źródło
2

aby uniknąć zmiany

  • Prawie poddomenaA.example.com
  • subdomenaA.example.comp.other

ale nadal

  • subdomenaA.example.com.IsIt.good

(może nie jest dobry pomysł na rootowanie domeny)

find /home/www/ -type f -exec sed -i 's/\bsubdomainA\.example\.com\b/\1subdomainB.example.com\2/g' {} \;
NeronLeVelu
źródło
2

Po prostu używam bluzek:

find . -name '*.[c|cc|cp|cpp|m|mm|h]' -print0 |  xargs -0 tops -verbose  replace "verify_noerr(<b args>)" with "__Verify_noErr(<args>)" \
replace "check(<b args>)" with "__Check(<args>)" 
tgunr
źródło
plus jeden za „'*. [c | cc | cp | cpp | m | mm | h]' '
FractalSpace
2

Oto wersja, która powinna być bardziej ogólna niż większość; nie wymaga na przykład find( duzamiast tego używania ). To wymaga xargs, które można znaleźć tylko w niektórych wersjach Planu 9 (np. 9front).

 du -a | awk -F' '  '{ print $2 }' | xargs sed -i -e 's/subdomainA\.example\.com/subdomainB.example.com/g'

Jeśli chcesz dodać filtry, takie jak rozszerzenia plików, użyj grep:

 du -a | grep "\.scala$" | awk -F' '  '{ print $2 }' | xargs sed -i -e 's/subdomainA\.example\.com/subdomainB.example.com/g'
barker
źródło
1

Dla Qshell (qsh) na IBMi, nie bash jak oznaczono OP.

Ograniczenia poleceń qsh:

  • find nie ma opcji -print0
  • xargs nie ma opcji -0
  • sed nie ma opcji -i

Zatem rozwiązanie w qsh:

    PATH='your/path/here'
    SEARCH=\'subdomainA.example.com\'
    REPLACE=\'subdomainB.example.com\'

    for file in $( find ${PATH} -P -type f ); do

            TEMP_FILE=${file}.${RANDOM}.temp_file

            if [ ! -e ${TEMP_FILE} ]; then
                    touch -C 819 ${TEMP_FILE}

                    sed -e 's/'$SEARCH'/'$REPLACE'/g' \
                    < ${file} > ${TEMP_FILE}

                    mv ${TEMP_FILE} ${file}
            fi
    done

Ostrzeżenia:

  • Rozwiązanie wyklucza obsługę błędów
  • Nie Bash oznaczony jako OP
Christoff Erasmus
źródło
Ma to pewne irytujące problemy z cytowaniem, a także czytaniem wierszy for.
tripleee
1

Jeśli chcesz użyć tego bez całkowitego zniszczenia repozytorium SVN, możesz powiedzieć „znajdź”, aby zignorował wszystkie ukryte pliki, wykonując:

find . \( ! -regex '.*/\..*' \) -type f -print0 | xargs -0 sed -i 's/subdomainA.example.com/subdomainB.example.com/g'
Marcus Floyd
źródło
Nawiasy wydają się zbyteczne. Wcześniej występował błąd formatowania, który uniemożliwiał jego użycie (renderowanie Markdown zjadłoby niektóre znaki z wyrażenia regularnego).
tripleee
1

Używanie kombinacji grepised

for pp in $(grep -Rl looking_for_string)
do
    sed -i 's/looking_for_string/something_other/g' "${pp}"
done
Paweł
źródło
@tripleee Zmodyfikowałem to trochę. W tym przypadku dane wyjściowe dla grep -Rl patternwygenerowanej przez polecenia listy plików, w których znajduje się wzorzec. Pliki nie są odczytywane w forpętli.
Paweł
Co? Nadal masz forpętlę; jeśli jakakolwiek zwrócona nazwa pliku zawiera białe znaki, nie będzie działać poprawnie, ponieważ powłoka tokenizuje forlistę argumentów. Ale potem używasz zmiennej nazwy pliku bez cudzysłowów w pętli, więc zamiast tego pękłaby tam, jeśli to naprawisz. Poprawienie pozostałych błędów sprawi, że twoje będą identyczne z odpowiedzią @ MadMan2064.
tripleee
@tripleee tak, to prawda, tęskniłem za tym.
Paweł
1

Aby zamienić wszystkie wystąpienia w repozytorium git, możesz użyć:

git ls-files -z | xargs -0 sed -i 's/subdomainA\.example\.com/subdomainB.example.com/g'

Zobacz Lista plików w lokalnym repozytorium git? dla innych opcji, aby wyświetlić listę wszystkich plików w repozytorium. Te -zopcje mówi git oddzielić nazwy plików z bajtem zerowym, który zapewnia, że xargs(z opcją -0) można oddzielić nazwy plików, nawet jeśli zawierają one spacje lub etażerka.

Perseidy
źródło
1
perl -p -i -e 's/oldthing/new_thingy/g' `grep -ril oldthing *`
Sheena
źródło
1
Nieużywanie awk/ sed, ale Perl jest powszechny (z wyjątkiem systemów wbudowanych / tylko z zajęty).
pevik