Menggunakan shell seperti bash atau zshell, bagaimana saya bisa melakukan 'temukan dan ganti' secara rekursif? Dengan kata lain, saya ingin mengganti setiap kemunculan 'foo' dengan 'bar' di semua file dalam direktori ini dan subdirektori.
bash
shell
zsh
find-and-replace
Nathan Long
sumber
sumber
Jawaban:
Perintah ini akan melakukannya (diuji pada Mac OS X Lion dan Kubuntu Linux).
Begini cara kerjanya:
find . -type f -name '*.txt'
menemukan, dalam direktori saat ini (.
) dan di bawah, semua file biasa (-type f
) yang namanya berakhir dengan.txt
|
meneruskan output dari perintah itu (daftar nama file) ke perintah berikutnyaxargs
mengumpulkan nama file itu dan menyerahkannya satu per satu kesed
sed -i '' -e 's/foo/bar/g'
berarti "mengedit file di tempat, tanpa cadangan, dan melakukan penggantian berikut (s/foo/bar
) beberapa kali per baris (/g
)" (lihatman sed
)Perhatikan bahwa bagian 'tanpa cadangan' di baris 4 OK untuk saya, karena file yang saya ubah berada di bawah kontrol versi, jadi saya dapat dengan mudah membatalkan jika ada kesalahan.
sumber
-print0
opsi. Perintah Anda akan gagal pada file dengan spasi dll dalam namanya.find -name '*.txt' -exec sed -i 's/foo/bar/g' {} +
lakukan semua ini dengan GNU find.sed: can't read : No such file or directory
ketika saya menjalankanfind . -name '*.md' -print0 | xargs -0 sed -i '' -e 's/ä/ä/g'
, tetapifind . -name '*.md' -print0
memberikan daftar banyak file.-i
dan''
''
setelahsed -i
apa''
peran?Ini menghilangkan
xargs
ketergantungan.sumber
sed
, jadi akan gagal pada kebanyakan sistem. GNUsed
mengharuskan Anda untuk tidak memberi jarak antara-i
dan''
.Jika Anda menggunakan Git maka Anda dapat melakukan ini:
-l
hanya mencantumkan nama file.-z
mencetak byte nol setelah setiap hasil.Saya akhirnya melakukan ini karena beberapa file dalam proyek tidak memiliki baris baru di akhir file, dan menambahkan baris baru bahkan ketika itu tidak membuat perubahan lain. (Tidak ada komentar apakah file harus memiliki baris baru di akhir. 🙂)
sumber
find ... -print0 | xargs -0 sed ...
solusi tidak hanya membutuhkan waktu lebih lama tetapi juga menambahkan baris baru ke file yang belum memilikinya, yang merupakan gangguan ketika bekerja di dalam git repo.git grep
pencahayaan cepat sebagai perbandingan.Inilah fungsi zsh / perl saya yang saya gunakan untuk ini:
Dan saya akan mengeksekusinya menggunakan
(sebagai contoh)
sumber
Mencoba:
Diuji pada Ubuntu 12,04.
Perintah ini TIDAK akan berfungsi jika nama subdirektori dan / atau nama file mengandung spasi, tetapi jika Anda memilikinya, jangan gunakan perintah ini karena tidak akan berfungsi.
Ini adalah praktik yang buruk untuk menggunakan spasi dalam nama direktori dan nama file.
http://linuxcommand.org/lc3_lts0020.php
Lihat "Fakta penting tentang nama file"
sumber
Gunakan Script Shell ini
Saya sekarang menggunakan skrip shell ini, yang menggabungkan hal-hal yang saya pelajari dari jawaban lain dan dari pencarian di web. Saya menempatkannya di file yang disebut
change
folder$PATH
dan saya lakukanchmod +x change
.sumber
Kasus penggunaan saya adalah saya ingin mengganti
foo:/Drive_Letter
denganfoo:/bar/baz/xyz
Dalam kasus saya, saya bisa melakukannya dengan kode berikut. Saya berada di lokasi direktori yang sama di mana ada banyak file.harapan itu membantu.
sumber
Perintah berikut bekerja dengan baik di Ubuntu dan CentOS; Namun, di bawah OS XI terus mendapatkan kesalahan:
Ketika saya mencoba melewati params melalui xargs itu berfungsi dengan baik tanpa kesalahan:
sumber
-i
menjadi-i ''
mungkin lebih relevan daripada fakta bahwa Anda berubah-exec
menjadi-print0 | xargs -0
. BTW, Anda mungkin tidak perlu-e
.Di atas berfungsi seperti pesona, tetapi dengan direktori yang ditautkan, saya harus menambahkan
-L
bendera padanya. Versi finalnya terlihat seperti:sumber