Muszę zamienić ciąg w wielu plikach w folderze, z ssh
dostępem tylko do serwera. W jaki sposób mogę to zrobić?
460
cd /path/to/your/folder
sed -i 's/foo/bar/g' *
Wystąpienia „foo” zostaną zastąpione przez „bar”.
W systemach BSD, takich jak macOS, musisz zapewnić rozszerzenie kopii zapasowej, takie jak -i '.bak'
„ryzyko uszkodzenia lub częściowej zawartości” na stronę podręcznika.
cd /path/to/your/folder
sed -i '.bak' 's/foo/bar/g' *
sed
,-i
wymaga ciąg po nim, który jest dołączany do starych nazw plików.sed -i .bak 's/foo/bar/g' *.xx
Przenosi więc wszystkie.xx
pliki na równoważne.xx.bak
nazwy, a następnie generuje.xx
pliki z podstawieniem foo → bar.sed -i 's/foo\ with\ spaces/bar/g' *
. Przypuszczam, że dowiedziałeś się po tak długim czasie ... ale w ten sposób pozostanie to dla innych, którzy znajdą ten sam problem.sed -i -e 's/foo/bar/g' $(find /home/user/base/dir)
Podobne do odpowiedzi Kaspara, ale z flagą g, która zastępuje wszystkie wystąpienia w linii.
W przypadku globalnej nie uwzględniającej wielkości liter:
źródło
LC_ALL=C find ./ -type f -exec sed -i '' -e 's/proc.priv/priv/g' {} \;
(zobacz ten post i ten )--include=*.whatever
pomocą opcji -r.git/
. Pamiętaj, abycd
zejść na niższy poziom.git status
powraca:error: bad index file sha1 signature.... fatal: index file corrupt
. Co daje?Odpowiedź @ kev jest dobra, ale wpływa tylko na pliki w bezpośrednim katalogu. Poniższy przykład używa grep do rekurencyjnego wyszukiwania plików. Działa dla mnie za każdym razem.
Podział poleceń
grep -r : --recursive , rekurencyjnie odczytuje wszystkie pliki w każdym katalogu.
grep -l : --print-with-mecze , drukuje nazwę każdego pliku, który ma dopasowanie, zamiast wypisywać pasujące linie.
grep -i : --ignore-case .
xargs : przekształć STDIN na argumenty, postępuj zgodnie z tą odpowiedzią .
Komenda xargs -i @ ~ zawiera @ ~ : symbol zastępczy dla argumentu, który ma być użyty w określonej pozycji w komendzie ~ , znak @ to symbol zastępczy, który można zastąpić dowolnym łańcuchem.
sed -i : edytuj pliki w miejscu, bez kopii zapasowych.
sed s / regexp / replace / : zastępuj ciąg pasujący wyrażenie regularne z zamianą .
sed s / regexp / replace / g : global , dokonaj podstawienia dla każdego dopasowania zamiast tylko pierwszego.
źródło
grep --include={*.php,*.html,*.js} -rnl './' -e "old-word" | xargs -i@ sed -i 's/old-word/new-word/g' @
|
tym, dlaczego-i
w komendzie xargs? Przeczytałem w instrukcji, że jest przestarzała i należy jej użyć-I
. I czy jest@
używany jako ogranicznik początku i końca wzorca?grep -rli 'old-word' * | xargs -I@ sed -i '' 's/2.0.0/latest/g' @
rli
) i@
znak, na przykładTo działało dla mnie:
Howerver, to nie:
sed -i 's/string1/string2/g' *
. Może „foo” nie miało być string1, a „bar” nie string2.źródło
find ./ -type f -exec sed -i '' -e 's/string1/string2/' {} \;
Istnieje kilka standardowych odpowiedzi na to pytanie. Zasadniczo można użyć polecenia find, aby rekurencyjnie wyświetlić listę plików, a następnie wykonać operacje za pomocą sed lub perl .
W przypadku większości szybkich zastosowań może okazać się, że polecenie rpl jest znacznie łatwiejsze do zapamiętania. Oto zamiennik (foo -> pasek), rekurencyjnie dla wszystkich plików:
rpl -R foo bar .
Prawdopodobnie będziesz musiał go zainstalować (
apt-get install rpl
lub podobny).Jednak w przypadku trudniejszych zadań, które wymagają wyrażeń regularnych i podstawiania wstecz lub zmian nazw plików, a także wyszukiwania i zamiany, najbardziej ogólnym i potężnym narzędziem, o którym wiem, jest repren , niewielki skrypt Pythona, dla którego napisałem jakiś czas temu bardziej wymagające zmiany nazw i refaktoryzacji. Powody, dla których możesz to preferować to:
Aby go użyć,
pip install repren
. Sprawdź README dla przykładów.źródło
Aby zamienić ciąg w wielu plikach, możesz użyć:
Na przykład
Blog źródłowy
źródło
Aby zamienić ścieżkę w plikach (unikając znaków specjalnych), możesz użyć następującego polecenia:
Znak @ oznacza, że wszystkie znaki specjalne należy zignorować w następującym ciągu.
źródło
Jeśli Twój ciąg zawiera ukośnik (/), możesz zmienić separator na „+”.
To polecenie uruchomi się rekurencyjnie w bieżącym katalogu.
źródło
../domain.com
dodomain.com
Wystąpienia pierwszego wiersza wyrażenia „foo” zostaną zastąpione wyrazem „bar”. I możesz użyć drugiej linii do sprawdzenia.
źródło
grep -rl 'foo' . | xargs sed -i 's/foo/bar/g'
Jeśli masz listę plików, których możesz użyć
Jeśli masz wszystkie pliki, których możesz użyć
Jeśli masz listę plików z rozszerzeniem, możesz użyć
źródło
replace "old_string" "new_string" -- *.txt
replace
narzędzie. Bez tych informacji odpowiedź jest niepełna.„Możesz także użyć find i sed, ale uważam, że ta mała linia perla działa dobrze.
„(Fragment z http://www.liamdelahunty.com/tips/linux_search_and_replace_multiple_files.php )
Moje najlepsze wyniki pochodzą z używania perla i grepa (aby upewnić się, że plik ma wyrażenie wyszukiwania)
źródło
Biorąc pod uwagę, że chcesz wyszukać ciąg
search
i zastąpić goreplace
wieloma plikami, oto moja sprawdzona w bitwie formuła jednoliniowa :Szybkie wyjaśnienie grep:
-R
- wyszukiwanie rekurencyjne-i
- bez rozróżniania wielkości liter-I
- pomiń pliki binarne (chcesz tekst, prawda?)-l
- wydrukuj prostą listę jako wynik. Potrzebny do innych poleceńDane wyjściowe grep są następnie przesyłane potokowo do sed (przez xargs), który jest używany do faktycznego zastąpienia tekstu.
-i
Flaga zmieni plik bezpośrednio. Usuń go, aby uzyskać rodzaj trybu „pracy na sucho”.źródło
Wymyśliłem własne rozwiązanie, zanim znalazłem to pytanie (i odpowiedzi). Szukałem różnych kombinacji „zamień”, „kilka” i „xml”, ponieważ taka była moja aplikacja, ale nie znalazłem tej konkretnej.
Mój problem: miałem wiosenne pliki XML z danymi dla przypadków testowych, zawierające złożone obiekty. Refaktor kodu źródłowego Java zmienił wiele klas i nie dotyczył plików danych XML. Aby zapisać dane przypadków testowych, musiałem zmienić wszystkie nazwy klas we wszystkich plikach xml, rozproszonych w kilku katalogach. Wszystko podczas zapisywania kopii zapasowych oryginalnych plików XML (choć nie było to konieczne, ponieważ kontrola wersji uratowałaby mnie tutaj).
Szukałem kombinacji
find
+sed
, ponieważ działało to dla mnie w innych sytuacjach, ale nie z kilkoma zastąpieniami na raz.Potem znalazłem odpowiedź pytaj ubuntu i pomogło mi to zbudować linię poleceń:
I działało idealnie (cóż, moja skrzynia miała sześć różnych zamienników). Pamiętaj jednak, że dotknie wszystkich plików * .xml w bieżącym katalogu. Z tego powodu, a jeśli jesteś odpowiedzialny za system kontroli wersji, możesz najpierw filtrować i przekazywać tylko
sed
tym, którzy faktycznie mają ciągi, które chcesz; lubić:źródło
findstr /spin /c:"quéquieresbuscar" *.xml
.źródło
Naprawdę kiepski, ale nie mogłem zmusić żadnego z poleceń sed do działania bezpośrednio na OSX, więc zamiast tego zrobiłem to głupie:
^ - skopiuj te trzy linie do mojego schowka (tak, dołącz końcowy znak nowej linii), a następnie:
vi *
i przytrzymaj Command-V, aż powie, że nie ma już plików.
Głupi ... hacky ... skuteczny ...
źródło
Na MacBooku Pro użyłem następujących (inspirowanych https://stackoverflow.com/a/19457213/6169225 ):
źródło
-e
po prostu mówi sed, że następny token jest poleceniem. W przypadku rozszerzonych wyrażeń regularnych użyj-E
zamiast tego.Edytor strumienia modyfikuje wiele plików „w miejscu” po wywołaniu z
-i
przełącznikiem, który przyjmuje plik kopii zapasowej kończący się jako argument. Więczastępuje
foo
zebar
wszystkich plików w tym folderze, ale nie zejść do podfolderów. Spowoduje to jednak wygenerowanie nowego.bak
pliku dla każdego pliku w katalogu. Aby zrobić to rekurencyjnie dla wszystkich plików w tym katalogu i wszystkich jego podkatalogach, potrzebujesz pomocnika, takiego jakfind
, przechodzącego przez drzewo katalogów.find
pozwala na dalsze ograniczenia plików, które należy modyfikować, podając dalsze argumenty, takie jakfind ./ -name '*.php' -or -name '*.html' -print0
w razie potrzeby.Uwaga: GNU
sed
nie wymaga zakończenia pliku,sed -i 's/foo/bar/g' *
będzie również działać; FreeBSDsed
wymaga rozszerzenia, ale pozwala na spację między nimi, więcsed -i .bak s/foo/bar/g *
działa.źródło
skrypt do komendy multiedit
Z odpowiedzi Kaspara zrobiłem skrypt bash, aby zaakceptować argumenty wiersza poleceń i opcjonalnie ograniczyć nazwy plików pasujące do wzorca. Zapisz w $ PATH i uczyń plik wykonywalny, a następnie po prostu użyj powyższej komendy.
Oto skrypt:
źródło
Jeśli plik zawiera odwrotne ukośniki (zwykle ścieżki), możesz spróbować czegoś takiego:
dawny:
źródło
Aby zachować mój osobisty angielski węzeł, napisałem skrypt narzędzia, który pomaga zastąpić wiele par starych / nowych ciągów dla wszystkich plików w katalogu rekurencyjnie.
Wiele par starych / nowych ciągów jest zarządzanych na mapie mieszającej.
Katalog można ustawić za pomocą wiersza polecenia lub zmiennej środowiskowej, mapa jest na stałe zakodowana w skrypcie, ale w razie potrzeby można zmodyfikować kod, aby ładował się z pliku.
Wymaga bash 4.2, ze względu na nową funkcję.
en_standardize.sh:
źródło
Użycie polecenia ack byłoby znacznie szybsze:
Również jeśli w wyniku wyszukiwania masz białą spację. Musisz uciec.
źródło
Podaję przykład naprawy typowego błędu shebang w źródłach Pythona.
Możesz wypróbować podejście grep / sed. Oto taki, który działa z GNU sed i nie złamie repozytorium git:
Lub możesz użyć greptile :)
Właśnie przetestowałem pierwszy skrypt, a drugi również powinien działać. Uważaj na znaki ucieczki, myślę, że w większości przypadków powinno być łatwiej używać greptile. Oczywiście możesz robić wiele interesujących rzeczy za pomocą sed, a do tego może być lepiej opanować używanie go z xargs.
źródło
Znalazłem ten jeden z drugiego wpisu (nie pamiętam, który) i chociaż nie jest najbardziej elegancki, jest prosty i jako początkujący użytkownik Linuksa nie sprawił mi żadnych problemów
jeśli masz spacje lub inne znaki specjalne, użyj \
dla ciągów w podkatalogach użyj **
źródło
Poniższego polecenia można użyć do pierwszego wyszukiwania plików i zamiany plików:
Na przykład
źródło
Jest prostszy sposób, używając prostego pliku skryptu:
otwórz plik w gedit lub edytorze do wyboru, używam gedit tutaj.
Następnie w edytorze wklej następujące elementy do pliku
Zapisz plik, zamknij gedit , a następnie zamknij terminal lub po prostu zamknij go, a następnie uruchom, aby móc załadować nowy skrypt, który dodałeś.
Przejdź do katalogu, w którym masz wiele plików, które chcesz edytować. Następnie uruchomić:
Naciśnij Enter, a to automatycznie zastąpi stary ciąg i stary ciąg 1 we wszystkich plikach, które je zawierają, poprawnym nowym ciągiem i newstring1 .
Pominie wszystkie katalogi i pliki, które nie zawierają starych ciągów.
Może to pomóc w wyeliminowaniu żmudnej pracy związanej z pisaniem w przypadku, gdy masz wiele katalogów z plikami, które wymagają zamiany ciągów. Wszystko, co musisz zrobić, to przejść do każdego z tych katalogów, a następnie uruchomić:
#replace_string_files_present_dir
Wszystko, co musisz zrobić, to upewnić się, że uwzględniłeś lub dodałeś wszystkie ciągi zastępujące, jak pokazałem powyżej:
replace "oldstring" "newstring" -- *
na końcu pliku / bin / replace_string_files_present_dir .
Aby dodać nowy ciąg zastępujący, wystarczy otworzyć skrypt, który utworzyliśmy, wpisując w terminalu:
sudo gedit /bin/replace_string_files_present_dir
Nie martw się o liczbę dodawanych ciągów zastępujących, nie będą one działać, jeśli nie zostanie znaleziony stary ciąg .
źródło
.gitlab-ci.yml
lub atravis.yml
). Każda kolejna zmiana polegająca na napisaniu skryptu w celu jego późniejszego wykonania jest anty-wzorcem, ponieważ wtedy będziesz musiał napisać skrypt do tworzenia skryptu (a ja przez większość czasu mam bałagan)$ replace "From" "To" - `find / path / to / folder -type f`
(replace - narzędzie do zamiany napisów w systemie baz danych MySQL)
źródło