Jawaban:
cd /path/to/your/folder
sed -i 's/foo/bar/g' *
Kemunculan "foo" akan diganti dengan "bar".
Pada sistem BSD seperti macOS, Anda perlu memberikan ekstensi cadangan seperti -i '.bak'
atau "risiko risiko atau konten parsial" lainnya atau per halaman manual.
cd /path/to/your/folder
sed -i '.bak' 's/foo/bar/g' *
sed
, -i
membutuhkan string setelahnya, yang ditambahkan ke nama file lama. Jadi sed -i .bak 's/foo/bar/g' *.xx
pindahkan semua .xx
file ke .xx.bak
nama yang setara dan kemudian hasilkan .xx
file dengan substitusi foo → bar.
sed -i 's/foo\ with\ spaces/bar/g' *
. Saya kira Anda sudah tahu setelah sekian lama ... tetapi cara ini tetap untuk orang lain menemukan masalah yang sama.
sed -i -e 's/foo/bar/g' $(find /home/user/base/dir)
Mirip dengan jawaban Kaspar tetapi dengan flag g untuk menggantikan semua kemunculan pada sebuah garis.
find ./ -type f -exec sed -i 's/string1/string2/g' {} \;
Untuk case global tidak sensitif:
find ./ -type f -exec sed -i 's/string1/string2/gI' {} \;
LC_ALL=C find ./ -type f -exec sed -i '' -e 's/proc.priv/priv/g' {} \;
(lihat posting ini dan ini )
--include=*.whatever
dengan -r
.git/
. Pastikan untuk cd
turun ke level yang lebih rendah.
git status
kembali: error: bad index file sha1 signature.... fatal: index file corrupt
. Apa yang menyebabkannya?
Jawaban @ kev baik, tetapi hanya memengaruhi file di direktori langsung. Contoh di bawah ini menggunakan grep untuk menemukan file secara rekursif. Ini bekerja untuk saya setiap saat.
grep -rli 'old-word' * | xargs -i@ sed -i 's/old-word/new-word/g' @
Perintah rusak
grep -r : --recursive , secara rekursif membaca semua file di bawah setiap direktori.
grep -l : --print-with-cocok , mencetak nama setiap file yang memiliki kecocokan, bukan mencetak baris yang cocok.
grep -i : --ignore-case .
xargs : mengubah STDIN menjadi argumen, ikuti jawaban ini .
Perintah xargs -i @ ~ berisi @ ~ : pengganti untuk argumen yang akan digunakan pada posisi tertentu dalam ~ perintah ~ , tanda @ adalah pengganti yang bisa diganti dengan string apa pun.
sed -i : mengedit file di tempat, tanpa cadangan.
sed s / regexp / replacement / : pengganti senar string regexp dengan penggantian .
sed s / regexp / replacement / g : global , buat substitusi untuk setiap pertandingan, bukan hanya pertandingan pertama.
grep --include={*.php,*.html,*.js} -rnl './' -e "old-word" | xargs -i@ sed -i 's/old-word/new-word/g' @
|
, juga, mengapa -i
dalam perintah xargs? Saya membaca dalam manual itu sudah usang dan harus digunakan -I
sebagai gantinya. Dan @
digunakan sebagai pembatas untuk awal dan akhir untuk pola?
grep -rli 'old-word' * | xargs -I@ sed -i '' 's/2.0.0/latest/g' @
rli
) dan @
tanda misalnya
Ini bekerja untuk saya:
find ./ -type f -exec sed -i 's/string1/string2/' {} \;
Howerver, ini tidak: sed -i 's/string1/string2/g' *
. Mungkin "foo" tidak dimaksudkan sebagai string1 dan "bar" bukan string2.
find ./ -type f -exec sed -i '' -e 's/string1/string2/' {} \;
Ada beberapa jawaban standar untuk ini sudah terdaftar. Secara umum, Anda dapat menggunakan find untuk mendaftarkan file secara rekursif dan kemudian melakukan operasi dengan sed atau perl .
Untuk sebagian besar penggunaan cepat, Anda mungkin menemukan perintah rpl jauh lebih mudah diingat. Berikut ini adalah penggantian (foo -> bar), secara rekursif pada semua file:
rpl -R foo bar .
Anda mungkin harus menginstalnya (apt-get install rpl
atau serupa).
Namun, untuk pekerjaan yang lebih sulit yang melibatkan ekspresi reguler dan penggantian belakang, atau mengganti nama file serta mencari dan mengganti, alat paling umum dan kuat yang saya ketahui adalah repren , skrip Python kecil yang saya tulis beberapa waktu lalu untuk beberapa penggantian nama dan tugas refactoring yang lebih sulit. Alasan yang mungkin Anda sukai adalah:
Untuk menggunakannya pip install repren
,. Periksa README untuk contoh.
Untuk mengganti string di banyak file, Anda dapat menggunakan:
grep -rl string1 somedir/ | xargs sed -i 's/string1/string2/g'
Misalnya
grep -rl 'windows' ./ | xargs sed -i 's/windows/linux/g'
Untuk mengganti jalur di dalam file (menghindari karakter melarikan diri), Anda dapat menggunakan perintah berikut:
sed -i 's@old_path@new_path@g'
Tanda @ berarti bahwa semua karakter khusus harus diabaikan dalam string berikut.
Jika string Anda memiliki garis miring (/) di dalamnya, Anda bisa mengubah pembatas menjadi '+'.
find . -type f -exec sed -i 's+http://example.com+https://example.com+g' {} +
Perintah ini akan berjalan secara rekursif di direktori saat ini.
../domain.com
kedomain.com
Kejadian baris pertama dari "foo" akan diganti dengan "bar". Dan Anda dapat menggunakan baris kedua untuk memeriksa.
grep -rl 'foo' . | xargs sed -i 's/foo/bar/g'
grep 'foo' -r * | awk -F: {'print $1'} | sort -n | uniq -c
grep -rl 'foo' . | xargs sed -i 's/foo/bar/g'
Jika Anda memiliki daftar file yang dapat Anda gunakan
replace "old_string" "new_string" -- file_name1 file_name2 file_name3
Jika Anda memiliki semua file yang dapat Anda gunakan
replace "old_string" "new_string" -- *
Jika Anda memiliki daftar file dengan ekstensi, Anda dapat menggunakan
replace "old_string" "new_string" -- *.extension
replace "old_string" "new_string" -- *.txt
replace
utilitas ini . Tanpa informasi ini, jawaban ini tidak lengkap.
"Kamu juga bisa menggunakan find dan sed, tetapi aku menemukan bahwa garis kecil perl ini bekerja dengan baik.
perl -pi -w -e 's/search/replace/g;' *.php
"(Diekstrak dari http://www.liamdelahunty.com/tips/linux_search_and_replace_multiple_files.php )
Hasil terbaik saya berasal dari menggunakan perl dan grep (untuk memastikan file memiliki ekspresi pencarian)
perl -pi -w -e 's/search/replace/g;' $( grep -rl 'search' )
Mengingat Anda ingin mencari string search
dan menggantinya dengan replace
banyak file, ini adalah formula satu-baris saya yang telah teruji pertempuran :
grep -RiIl 'search' | xargs sed -i 's/search/replace/g'
Penjelasan grep cepat:
-R
- Pencarian rekursif-i
- case-insensitive-I
- lewati file biner (Anda ingin teks, bukan?)-l
- cetak daftar sederhana sebagai keluaran. Dibutuhkan untuk perintah lainOutput grep kemudian disalurkan ke sed (melalui xargs) yang digunakan untuk benar-benar mengganti teks. The -i
bendera akan mengubah file secara langsung. Hapus itu untuk semacam mode "dry run".
Saya membuat solusi sendiri sebelum saya menemukan pertanyaan ini (dan jawaban). Saya mencari berbagai kombinasi "ganti" "beberapa" dan "xml," karena itu adalah aplikasi saya, tetapi tidak menemukan yang satu ini.
Masalah saya: Saya punya file pegas xml dengan data untuk kasus uji, yang berisi objek kompleks. Refactor pada kode sumber java mengubah banyak kelas dan tidak berlaku untuk file data xml. Untuk menyimpan data kasus uji, saya perlu mengubah semua nama kelas di semua file xml, didistribusikan di beberapa direktori. Semua sambil menyimpan salinan cadangan dari file xml asli (meskipun ini bukan keharusan, karena kontrol versi akan menyelamatkan saya di sini).
Saya mencari beberapa kombinasi find
+ sed
, karena berfungsi untuk saya dalam situasi lain, tetapi tidak dengan beberapa penggantian sekaligus.
Kemudian saya menemukan meminta respons ubuntu dan itu membantu saya membangun baris perintah:
find -name "*.xml" -exec sed -s --in-place=.bak -e 's/firstWord/newFirstWord/g;s/secondWord/newSecondWord/g;s/thirdWord/newThirdWord/g' {} \;
Dan itu bekerja dengan sempurna (well, case saya memiliki enam penggantian berbeda). Tetapi harap dicatat bahwa itu akan menyentuh semua file * .xml di bawah direktori saat ini. Karena itu, dan jika Anda bertanggung jawab pada sistem kontrol versi, Anda mungkin ingin memfilter terlebih dahulu dan hanya meneruskannya kepada sed
mereka yang benar-benar memiliki string yang Anda inginkan; Suka:
find -name "*.xml" -exec grep -e "firstWord" -e "secondWord" -e "thirdWord" {} \; -exec sed -s --in-place=.bak -e 's/firstWord/newFirstWord/g;s/secondWord/newSecondWord/g;s/thirdWord/newThirdWord/g' {} \;
findstr /spin /c:"quéquieresbuscar" *.xml
Ini akan berguna.
Benar-benar lumpuh, tapi saya tidak bisa mendapatkan perintah sed untuk bekerja dengan benar pada OSX, jadi saya melakukan hal bodoh ini sebagai gantinya:
:%s/foo/bar/g
:wn
^ - salin ketiga baris ini ke clipboard saya (ya, termasuk baris akhir), lalu:
vi *
dan tahan perintah-v sampai dikatakan tidak ada file yang tersisa.
Dumb ... hacky ... efektif ...
Di MacBook Pro, saya menggunakan yang berikut ini (terinspirasi oleh https://stackoverflow.com/a/19457213/6169225 ):
sed -i '' -e 's/<STR_TO_REPLACE>/<REPLACEMENT_STR>/g' *
-i ''
akan memastikan Anda tidak mengambil cadangan.
-e
untuk regex modern.
-e
hanya mengatakan bahwa token berikutnya adalah sebuah perintah. Untuk ekspresi reguler yang diperluas, gunakan -E
saja.
Editor aliran mengubah beberapa file “inplace” ketika dipanggil dengan -i
sakelar, yang mengambil file cadangan yang berakhir sebagai argumen. Begitu
sed -i.bak 's/foo/bar/g' *
menggantikan foo
dengan bar
semua file dalam folder ini, tetapi tidak turun ke subfolder. Namun ini akan menghasilkan .bak
file baru untuk setiap file di direktori Anda. Untuk melakukan ini secara rekursif untuk semua file di direktori ini dan semua subdirektori, Anda perlu bantuan, seperti find
, untuk melintasi pohon direktori.
find ./ -print0 | xargs -0 sed -i.bak 's/foo/bar/g' *
find
memungkinkan Anda pembatasan lebih lanjut pada file apa yang akan dimodifikasi, dengan menentukan argumen lebih lanjut seperti find ./ -name '*.php' -or -name '*.html' -print0
, jika perlu.
Catatan: GNU sed
tidak membutuhkan akhiran file, juga sed -i 's/foo/bar/g' *
akan berfungsi; FreeBSD sed
menuntut ekstensi, tetapi memungkinkan ruang di antaranya, jadi sed -i .bak s/foo/bar/g *
berfungsi.
skrip untuk perintah multiedit
multiedit [-n PATTERN] OLDSTRING NEWSTRING
Dari jawaban Kaspar saya membuat skrip bash untuk menerima argumen baris perintah dan secara opsional membatasi nama file yang cocok dengan suatu pola. Simpan $ PATH Anda dan buat executable, kemudian gunakan saja perintah di atas.
Ini skripnya:
#!/bin/bash
_help="\n
Replace OLDSTRING with NEWSTRING recursively starting from current directory\n
multiedit [-n PATTERN] OLDSTRING NEWSTRING\n
[-n PATTERN] option limits to filenames matching PATTERN\n
Note: backslash escape special characters\n
Note: enclose STRINGS with spaces in double quotes\n
Example to limit the edit to python files:\n
multiedit -n \*.py \"OLD STRING\" NEWSTRING\n"
# ensure correct number of arguments, otherwise display help...
if [ $# -lt 2 ] || [ $# -gt 4 ]; then echo -e $_help ; exit ; fi
if [ $1 == "-n" ]; then # if -n option is given:
# replace OLDSTRING with NEWSTRING recursively in files matching PATTERN
find ./ -type f -name "$2" -exec sed -i "s/$3/$4/g" {} \;
else
# replace OLDSTRING with NEWSTRING recursively in all files
find ./ -type f -exec sed -i "s/$1/$2/" {} \;
fi
Jika file tersebut berisi garis miring terbalik (biasanya jalur) Anda dapat mencoba sesuatu seperti ini:
sed -i -- 's,<path1>,<path2>,g' *
ex:
sed -i -- 's,/foo/bar,/new/foo/bar,g' *.sh (in all shell scripts available)
Untuk mempertahankan simpul bahasa Inggris pribadi saya, saya menulis sebuah skrip utilitas yang membantu mengganti beberapa pasangan string lama / baru, untuk semua file di bawah direktori secara rekursif.
Pasangan multipel string lama / baru dikelola di peta hash.
Dir dapat diatur melalui baris perintah atau variabel lingkungan, peta dikodekan dalam skrip, tetapi Anda dapat memodifikasi kode untuk memuat dari file, jika perlu.
Ini membutuhkan bash 4.2, karena beberapa fitur baru.
en_standardize.sh:
#! /bin/bash
# (need bash 4.2+,)
#
# Standardize phonetic symbol of English.
#
# format:
# en_standardize.sh [<dir>]
#
# params:
# * dir
# target dir, optional,
# if not specified then use environment variable "$node_dir_en",
# if both not provided, then will not execute,
# *
#
paramCount=$#
# figure target dir,
if [ $paramCount -ge 1 ]; then # dir specified
echo -e "dir specified (in command):\n\t$1\n"
targetDir=$1
elif [[ -v node_dir_en ]]; then # environable set,
echo -e "dir specified (in environment vairable):\n\t$node_dir_en\n"
targetDir=$node_dir_en
else # environable not set,
echo "dir not specified, won't execute"
exit
fi
# check whether dir exists,
if [ -d $targetDir ]; then
cd $targetDir
else
echo -e "invalid dir location:\n\t$targetDir\n"
exit
fi
# initial map,
declare -A itemMap
itemMap=( ["ɪ"]="i" ["ː"]=":" ["ɜ"]="ə" ["ɒ"]="ɔ" ["ʊ"]="u" ["ɛ"]="e")
# print item maps,
echo 'maps:'
for key in "${!itemMap[@]}"; do
echo -e "\t$key\t->\t${itemMap[$key]}"
done
echo -e '\n'
# do replace,
for key in "${!itemMap[@]}"; do
grep -rli "$key" * | xargs -i@ sed -i "s/$key/${itemMap[$key]}/g" @
done
echo -e "\nDone."
exit
Menggunakan perintah ack akan jauh lebih cepat seperti ini:
ack '25 Essex' -l | xargs sed -i 's/The\ fox \jump/abc 321/g'
Juga jika Anda memiliki ruang putih di hasil pencarian. Anda harus menghindarinya.
Saya memberikan contoh untuk memperbaiki kesalahan shebang umum dalam sumber python.
Anda dapat mencoba pendekatan grep / sed. Ini adalah yang berfungsi dengan GNU dan tidak akan merusak repo git:
$ grep -rli --exclude '*.git*' '#!/usr/bin/python' . | xargs -I {} \
gsed -i '' -e 's/#!\/usr\/bin\/python/#!\/usr\/bin\/env python/' {}
Atau Anda bisa menggunakan greptile :)
$ greptile -x .py -l -i -g '#!/usr/bin/env python' -r '#!/usr/bin/python' .
Saya baru saja menguji skrip pertama, dan yang kedua juga harus berfungsi. Hati-hati dengan karakter pelarian, saya pikir seharusnya lebih mudah menggunakan greptile dalam banyak kasus. Tentu saja, Anda dapat melakukan banyak hal menarik dengan sed, dan untuk itu mungkin lebih baik untuk menguasai menggunakannya dengan xargs.
Saya menemukan ini dari posting lain (tidak ingat yang mana) dan meskipun bukan yang paling elegan, itu sederhana dan sebagai pengguna Linux pemula telah memberi saya tidak ada masalah
for i in *old_str* ; do mv -v "$i" "${i/\old_str/new_str}" ; done
jika Anda memiliki spasi atau karakter khusus lainnya gunakan \
for i in *old_str\ * ; do mv -v "$i" "${i/\old_str\ /new_str}" ; done
untuk string dalam penggunaan sub-direktori **
for i in *\*old_str\ * ; do mv -v "$i" "${i/\old_str\ /new_str}" ; done
Ada cara yang lebih mudah dengan menggunakan file skrip sederhana:
# sudo chmod +x /bin/replace_string_files_present_dir
buka file di gedit atau editor pilihan Anda, saya menggunakan gedit di sini.
# sudo gedit /bin/replace_string_files_present_dir
Kemudian pada editor tempel yang berikut ini di dalam file
#!/bin/bash
replace "oldstring" "newstring" -- *
replace "oldstring1" "newstring2" -- *
#add as many lines of replace as there are your strings to be replaced for
#example here i have two sets of strings to replace which are oldstring and
#oldstring1 so I use two replace lines.
Simpan file, tutup gedit , lalu keluar dari terminal Anda atau tutup saja dan mulai untuk dapat memuat skrip baru yang Anda tambahkan.
Arahkan ke direktori tempat Anda memiliki banyak file yang ingin Anda edit. Lalu lari:
#replace_string_files_present_dir
Tekan enter dan ini akan secara otomatis mengganti oldstring dan oldstring1 di semua file yang berisi mereka dengan newstring yang benar dan newstring1 masing-masing.
Ini akan melewati semua direktori dan file yang tidak mengandung string lama.
Ini mungkin membantu menghilangkan pekerjaan mengetik yang membosankan jika Anda memiliki banyak direktori dengan file yang membutuhkan penggantian string. Yang harus Anda lakukan adalah menavigasi ke masing-masing direktori tersebut, lalu jalankan:
#replace_string_files_present_dir
Yang harus Anda lakukan adalah memastikan Anda telah memasukkan atau menambahkan semua string pengganti seperti yang saya tunjukkan di atas:
replace "oldstring" "newstring" -- *
di akhir file / bin / replace_string_files_present_dir .
Untuk menambahkan string pengganti yang baru, cukup buka skrip yang kami buat dengan mengetik berikut ini di terminal:
sudo gedit /bin/replace_string_files_present_dir
Jangan khawatir tentang jumlah string pengganti yang Anda tambahkan, mereka tidak akan berpengaruh jika tali lama tidak ditemukan.
.gitlab-ci.yml
atau a travis.yml
). Setiap putaran yang terdiri dari penulisan skrip untuk mengeksekusinya nanti adalah anti-pola, karena Anda akan perlu membuat skrip skrip (dan saya sering berantakan, sebagian besar waktu)
$ ganti "Dari" "Ke" - `find / path / ke / folder -type f`
(ganti - utilitas pengganti string dari Sistem Database MySQL)