Yalnızca değiştirilen dosyaların yedeklerini oluşturan bir sed yerinde değiştirme nasıl yapılır?


13

Geçerli çalışma dizinindeki tüm dosyalarda kullanılan bir terimi değiştirmek için aşağıdakileri çalıştırdım:

$ find . -type f -print0 | xargs -0 sed -i'.bup' -e's/Ms. Johnson/Mrs. Melbin/g'

Bu, sözcük değiştirme işlemini gerçekleştirdi, ancak dizeye .buphiç sahip olmayan dosya dosyaları da yarattı Ms. Johnson.

Tüm bu gereksiz yedeklemeleri oluşturmadan değişikliği nasıl yapabilirim?


bana sed görmek
Hotschke

Muhtemelen daha iyi bir yaklaşım mümkündür exve :!cp '%' '%.bup'kaydetmeden ve çıkmadan önce koşullu olarak (sadece dosya değiştirilirse) çalışır . Görmeye değmeli.
Wildcard

Ben yazdım yukarıda benim fikri hakkında soru üzerinde viyığın alışverişi.
Wildcard

Yanıtlar:


6

Dosyaların sedüzerinde çalışırken bir ikame yapılacağından emin olmak için dosyaların içeriğini kontrol edebilirsiniz:

find . \
    -type f \
    -exec grep -q 'Ms. Johnson' {} \; \
    -print0 |
xargs -0 sed -i'.bup' -e's/Ms. Johnson/Mrs. Melbin/g'

Bu konuda gerçekten akıllı olmak istiyorsanız, findhiç kullanmayı bırakabilirsiniz :

grep -Z -l -r 'Ms. Johnson' |
    xargs -0 sed -i'.bup' -e's/Ms. Johnson/Mrs. Melbin/g'

1
Bence '{}'senin \;de bundan hemen önce ihtiyacın var -exec.
Jander

8

Find -execöğesinde rasgele bir komut yürüten bir işleç var. Daha da iyisi, -execbir testtir , böylece birkaç -execs'yi birbirine zincirleyebilirsiniz ve daha önceki komutlar başarısız olursa, daha sonraki komutlar yürütülmez. Dize {}, geçerli dosya adıyla değiştirilir ;ve komutun sonunu işaretler. Kabuğun karışmasını önlemek için her ikisini de teklif etmelisiniz.

Yani:

find . -type f \
    -exec grep -q 'Ms. Johnson' '{}' \; \
    -exec sed -i'.bup' -e's/Ms. Johnson/Mrs. Melbin/g' '{}' \;

Hiç çıplak {} kullanmayla ilgili bir sorun yaşamadım.
amfetamachin

1
@amphetamachine: Bende yok, ama man sayfası bunu öneriyor. Bir csh şey olabilir veya küme {}ayracı genişletme yaparken boş dizeye genişleyen kabuklar (Bash değil POSIX değil) olabilir .
Jander

4

Adam sayfasına baktım ve sedsormadan önce yaptığınızdan emin olarak doğrudan bunu yapmanın bir yolunu görmedim. Grep kullanarak bu geçici çözüm bulmak için çeşitli yollar görüyorum, ancak bence en kolayı bu:

grep -rlZ "Ms. Johnson" . | xargs -0 sed -i'.bup' -e's/Ms. Johnson/Mrs. Melbin/g'

-rrecurse
-lprint dosya adı sadece
-Znull ile biten isimler


-1

Öncelikle arama terimlerinizle eşleşen dosyaların bir listesini oluşturmanız gerekir.

search="test"
for match in $(find -type f -exec grep -l $search "{}" \;)
do sed -i'.bup' -e "/$search/ s/$search/Mrs. Melbin/g" "$match"
done

.İlk argüman olarak unuttun find. Ayrıca, kendimi çok uzun zaman önce bilmediğim için, aslında alıntı yapmaktan veya kaçmak zorunda değilsiniz{}
Kevin

Dosyaların bir listesini oluşturmayın ve bunun üzerinde komut değiştirme işlemi gerçekleştirmeyin. İlk önce findsatırsonu ile ayrılmış bir dosya listesi oluşturur, daha sonra kabuk bu listeyi herhangi bir boşlukta (sadece satırsonu değil) ayırır ve sonra kabuk her kelimeyi bir küre deseni olarak ele alır. Bu yalnızca dosya adlarınız boşluk veya içermiyorsa işe yarar \[?*. Bu sayfadaki diğer cevaplar bunun nasıl doğru bir şekilde yapılacağını göstermektedir.
Gilles 'SO- kötü olmayı bırak'

@Kevin Bu ., find ile en azından gereksizdir (en azından linux'da bulunanı bul), çünkü hiçbir argümanın geçmediği varsayılır.
laebshade
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.