Відповіді:
cd /path/to/your/folder
sed -i 's/foo/bar/g' *
Виникнення "foo" буде замінено на "bar".
У таких системах BSD, як macOS, вам потрібно надати розширення для резервного копіювання, як-то -i '.bak'
або "ризик пошкодження або часткового вмісту" на сторінці сторінки.
cd /path/to/your/folder
sed -i '.bak' 's/foo/bar/g' *
sed
, -i
після неї потрібна рядок, яка додається до старих імен файлів. Таким чином sed -i .bak 's/foo/bar/g' *.xx
переміщує всі .xx
файли до еквівалентного .xx.bak
імені, а потім генерує .xx
файли з підстановою foo → bar.
sed -i 's/foo\ with\ spaces/bar/g' *
. Я гадаю, ви дізналися через стільки часу ... але таким чином залишається за іншими, що знаходять ту саму проблему.
sed -i -e 's/foo/bar/g' $(find /home/user/base/dir)
Схожий на відповідь Каспара, але з прапором g замінити всі події на рядку.
find ./ -type f -exec sed -i 's/string1/string2/g' {} \;
Для глобальної справи нечутливої:
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' {} \;
(див. Цю публікацію та цю )
--include=*.whatever
допомогою -r
.git/
. Обов’язково cd
опустіться на нижчий рівень.
git status
повертається: error: bad index file sha1 signature.... fatal: index file corrupt
. Що дає?
@ kev відповідь хороша, але впливає лише на файли в безпосередньому каталозі. У наведеному нижче прикладі використовується grep для рекурсивного пошуку файлів. Це працює для мене щоразу.
grep -rli 'old-word' * | xargs -i@ sed -i 's/old-word/new-word/g' @
Розбивка команд
grep -r : --рекурсивне , рекурсивно читати всі файли в кожному каталозі.
grep -l : --print-with- match, друкує ім'я кожного файлу, який має відповідність, замість того, щоб друкувати відповідні рядки.
grep -i : --ignore-case .
xargs : перетворіть STDIN в аргументи, дотримуйтесь цієї відповіді .
Команда xargs -i @ ~ містить @ ~ : заповнювач для аргументу, який буде використовуватися в певній позиції в команді ~ , знак @ є заповнювачем місця, який міг би замінити будь-який рядок.
sed -i : редагування файлів на місці, без резервного копіювання.
sed s / regexp / substitution / : замінити рядок, що відповідає regexp з заміною .
sed s / regexp / заміна / g : глобальна , зробіть заміну для кожного матчу замість лише першого.
grep --include={*.php,*.html,*.js} -rnl './' -e "old-word" | xargs -i@ sed -i 's/old-word/new-word/g' @
|
, також, чому -i
в xargs команді? Я читаю в посібнику, що застаріло, і -I
замість цього слід використовувати . І @
використовується як роздільник для початку та кінця для візерунка?
grep -rli 'old-word' * | xargs -I@ sed -i '' 's/2.0.0/latest/g' @
rli
) та @
знак, наприклад
Це працювало для мене:
find ./ -type f -exec sed -i 's/string1/string2/' {} \;
Howerver, це не зробив: sed -i 's/string1/string2/g' *
. Можливо, "foo" не мав на увазі бути string1, а "bar" - не string2.
find ./ -type f -exec sed -i '' -e 's/string1/string2/' {} \;
На це вже є кілька стандартних відповідей. Як правило, ви можете використовувати find для рекурсивного переліку файлів, а потім виконувати операції з sed або perl .
Для більшості швидких застосувань ви можете знайти команду rpl набагато простіше запам’ятати. Ось заміна (foo -> bar), рекурсивно для всіх файлів:
rpl -R foo bar .
Можливо, вам буде потрібно встановити його (apt-get install rpl
або подібне).
Однак для більш жорстких завдань, які передбачають регулярні вирази та підстановку назад, або перейменування файлів, а також пошук і заміна, найпоширеніший і найпотужніший інструмент, про який я знаю, є репрезентом , невеликим сценарієм Python, про який я писав деякий час назад завдання перейменування і рефакторингу терньє. Причини, які ви можете віддати перевагу, це:
Щоб використовувати його pip install repren
,. Перевірте README на приклади.
Для заміни рядка в декількох файлах ви можете використовувати:
grep -rl string1 somedir/ | xargs sed -i 's/string1/string2/g'
Напр
grep -rl 'windows' ./ | xargs sed -i 's/windows/linux/g'
Щоб замінити шлях у файлах (уникаючи втечі символів), ви можете скористатися такою командою:
sed -i 's@old_path@new_path@g'
Знак @ означає, що всі спеціальні символи слід ігнорувати у наступному рядку.
У випадку, якщо у вашій рядку є похила коса стрілка (/), ви можете змінити роздільник на "+".
find . -type f -exec sed -i 's+http://example.com+https://example.com+g' {} +
Ця команда буде виконуватися рекурсивно в поточному каталозі.
../domain.com
наdomain.com
Перший рядок вступу "foo" буде замінено на "bar". І ви можете використовувати другий рядок для перевірки.
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'
Якщо у вас є список файлів, які ви можете використовувати
replace "old_string" "new_string" -- file_name1 file_name2 file_name3
Якщо у вас є всі файли, які ви можете використовувати
replace "old_string" "new_string" -- *
Якщо у вас є список файлів з розширенням, ви можете використовувати
replace "old_string" "new_string" -- *.extension
replace "old_string" "new_string" -- *.txt
replace
утиліту. Без цієї інформації ця відповідь неповна.
"Ви також можете використовувати find і sed, але я вважаю, що ця маленька лінія Perl працює чудово.
perl -pi -w -e 's/search/replace/g;' *.php
"(Витягнуто з http://www.liamdelahunty.com/tips/linux_search_and_replace_multiple_files.php )
Мої найкращі результати отримують від використання perl та grep (щоб у файлі було вираження пошуку)
perl -pi -w -e 's/search/replace/g;' $( grep -rl 'search' )
З огляду на те, що ви хочете шукати рядок search
і замінювати його replace
на декілька файлів, це моя однорядкова формула, перевірена боєм :
grep -RiIl 'search' | xargs sed -i 's/search/replace/g'
Швидке пояснення пояснення:
-R
- рекурсивний пошук-i
- нечутливі до регістру-I
- пропустити бінарні файли (потрібен текст, правда?)-l
- друкувати простий список як вихід. Потрібно для інших командПотім висновок grep передається на sed (через xargs), який використовується для фактичної заміни тексту. -i
Прапор буде змінювати файл безпосередньо. Видаліть його для певного режиму «сухого пробігу».
Я придумав власне рішення, перш ніж знайшов це питання (і відповіді). Я шукав різні комбінації "замінити" "кілька" та "xml", тому що це було моїм додатком, але не знайшов цієї конкретної.
Моя проблема: у мене були весняні файли xml з даними для тестових випадків, що містять складні об'єкти. Рефактор у вихідному коді Java змінив багато класів і не застосовувався до файлів даних xml. Щоб зберегти дані тестових випадків, мені потрібно було змінити всі назви класів у всіх файлах xml, розподілених у кількох каталогах. Усі під час збереження резервних копій оригінальних файлів XML (хоча це не обов'язково, оскільки управління версіями врятує мене тут).
Я шукав якусь комбінацію find
+ sed
, тому що вона працювала на мене в інших ситуаціях, але не з кількома замінами одночасно.
Тоді я знайшов відповідь ubuntu у відповіді, і це допомогло мені побудувати свій командний рядок:
find -name "*.xml" -exec sed -s --in-place=.bak -e 's/firstWord/newFirstWord/g;s/secondWord/newSecondWord/g;s/thirdWord/newThirdWord/g' {} \;
І це спрацювало чудово (ну, мій випадок мав шість різних замін). Але зауважте, що він торкнеться всіх * .xml файлів у поточному каталозі. Через це, і якщо ви підзвітні системі контролю версій, ви можете спершу відфільтрувати і передати лише sed
тим, у кого є фактично потрібні рядки; подібно до:
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
Це буде зручно.
Насправді кульгавий, але я не зміг змусити жодної команди sed працювати правильно на OSX, тому я зробив цю тупу штуку замість цього:
:%s/foo/bar/g
:wn
^ - скопіюйте ці три рядки в мій буфер обміну (так, включіть закінчуючий новий рядок), потім:
vi *
і утримуйте команду v, поки не буде сказано, що файлів не залишилося.
Тупий ... хакі ... ефективний ...
У MacBook Pro я використав наступне (надихнув https://stackoverflow.com/a/19457213/6169225 ):
sed -i '' -e 's/<STR_TO_REPLACE>/<REPLACEMENT_STR>/g' *
-i ''
гарантує, що ви не робите резервних копій.
-e
для сучасної виразки.
-e
просто каже sed, що наступний маркер - це команда. Для розширених регулярних виразів використовуйте -E
замість цього.
Редактор потоку змінює декілька файлів «inplace», коли викликається -i
комутатором, який бере аргумент резервного файлу, що закінчується аргументом. Тому
sed -i.bak 's/foo/bar/g' *
замінює foo
з bar
у всіх файлах в цій папці, але не спускається в підкаталоги. Однак це створить новий .bak
файл для кожного файлу у вашому каталозі. Щоб зробити це рекурсивно для всіх файлів у цьому каталозі та всіх його підкаталогів, вам потрібен помічник, як-от find
, щоб перейти до дерева каталогів.
find ./ -print0 | xargs -0 sed -i.bak 's/foo/bar/g' *
find
дозволяє додатково обмежувати зміни файлів, вказуючи додаткові аргументи на зразок find ./ -name '*.php' -or -name '*.html' -print0
, якщо це необхідно.
Примітка: GNU sed
не вимагає закінчення файлу, він також sed -i 's/foo/bar/g' *
буде працювати; FreeBSD sed
вимагає розширення, але дозволяє простір між ними, тому sed -i .bak s/foo/bar/g *
працює.
скрипт для команди multiedit
multiedit [-n PATTERN] OLDSTRING NEWSTRING
З відповіді Каспара я створив сценарій bash, щоб прийняти аргументи командного рядка і необов'язково обмежити назви файлів, що відповідають шаблону. Збережіть у вашому $ PATH і зробіть виконуваний файл, а потім просто скористайтеся командою, наведеною вище.
Ось сценарій:
#!/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
Якщо файл містить зворотні риски (зазвичай, контури), ви можете спробувати щось подібне:
sed -i -- 's,<path1>,<path2>,g' *
колишній:
sed -i -- 's,/foo/bar,/new/foo/bar,g' *.sh (in all shell scripts available)
Щоб підтримувати свій особистий англійський вузол, я написав скрипт утиліти, який допомагає замінити кілька пар старого / нового рядка для всіх файлів у каталозі рекурсивно.
Кількома парами старий / новий рядок управляється в хеш-карті.
Режим можна встановити за допомогою командної лінії чи змінної середовища, карта жорстко закодована в сценарії, але ви можете змінити код для завантаження з файлу, якщо це необхідно.
Це вимагає bash 4.2, завдяки якійсь новій функції.
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
Використання команди ack було б набагато швидшим, як це:
ack '25 Essex' -l | xargs sed -i 's/The\ fox \jump/abc 321/g'
Також якщо у результатах пошуку є пробіл. Вам потрібно уникнути цього.
Я наводжу приклад для виправлення поширеної помилки shebang у джерелах python.
Ви можете спробувати підхід grep / sed. Ось такий, який працює з GNU sed і не порушує репортаж git:
$ grep -rli --exclude '*.git*' '#!/usr/bin/python' . | xargs -I {} \
gsed -i '' -e 's/#!\/usr\/bin\/python/#!\/usr\/bin\/env python/' {}
Або ви можете використовувати greptile :)
$ greptile -x .py -l -i -g '#!/usr/bin/env python' -r '#!/usr/bin/python' .
Я лише перевірив перший сценарій, а другий також повинен працювати. Будьте обережні з персонажами втечі, я думаю, що в більшості випадків використовувати грептил повинно бути простіше. Звичайно, ви можете зробити багато цікавих речей з sed, і для цього, можливо, бажано освоїти використання його з xargs.
Я знайшов цю з іншої публікації (не пам'ятаю, яка), і хоча це не найелегантніше, це просто і як початківець користувач Linux не дав мені ніяких проблем
for i in *old_str* ; do mv -v "$i" "${i/\old_str/new_str}" ; done
якщо у вас є пробіли чи інші спеціальні символи, використовуйте \
for i in *old_str\ * ; do mv -v "$i" "${i/\old_str\ /new_str}" ; done
для рядків у підкаталогах **
for i in *\*old_str\ * ; do mv -v "$i" "${i/\old_str\ /new_str}" ; done
Існує простіший спосіб за допомогою простого файлу сценарію:
# sudo chmod +x /bin/replace_string_files_present_dir
відкрийте файл у gedit або редакторі на ваш вибір, я тут використовую gedit.
# sudo gedit /bin/replace_string_files_present_dir
Потім у редактор вставити у файл наступне
#!/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.
Збережіть файл, закрийте gedit , потім вийдіть із терміналу або просто закрийте його, а потім запустіть його, щоб мати можливість завантажити новий доданий вами сценарій.
Перейдіть до каталогу, де у вас є кілька файлів, які ви хочете редагувати. Потім запустіть:
#replace_string_files_present_dir
Натисніть клавішу enter, і це автоматично замінить oldstring та oldstring1 у всіх файлах, що містять їх, на правильні newstring та newstring1 відповідно.
Він буде пропускати всі каталоги та файли, які не містять старих рядків.
Це може допомогти усунути нудну роботу введення тексту, якщо у вас є кілька каталогів з файлами, які потребують заміни рядка. Все, що вам потрібно зробити - це перейти до кожного з цих каталогів, а потім запустити:
#replace_string_files_present_dir
Все, що вам потрібно зробити, це переконатися, що ви включили або додали всі рядки заміни, як я вам показав вище:
replace "oldstring" "newstring" -- *
в кінці файлу / bin / substitu_string_files_present_dir .
Щоб додати новий рядок заміни, просто відкрийте створений нами сценарій, ввівши в терміналі наступне:
sudo gedit /bin/replace_string_files_present_dir
Не турбуйтеся про кількість доданих рядків заміни, вони не матимуть ефекту, якщо не буде знайдено oldstring .
.gitlab-ci.yml
чи a travis.yml
). Кожен поворот, що полягає у написанні сценарію, щоб виконати його пізніше, є анти-шаблоном, тому що вам тоді потрібно буде створити сценарій створення сценарію (і я безладдя, більшість часу)
$ замінити "Від" "До" - `знайти / шлях / до / папки -типу f`
(заміна - утиліта для заміни рядків системи баз даних MySQL)