Используя оболочку, такую как bash или zshell, как я могу сделать рекурсивный поиск и замену? Другими словами, я хочу заменить каждое вхождение 'foo' на 'bar' во всех файлах в этом каталоге и его подкаталогах.
bash
shell
zsh
find-and-replace
Натан Лонг
источник
источник
Ответы:
Эта команда сделает это (протестировано на Mac OS X Lion и Kubuntu Linux).
Вот как это работает:
find . -type f -name '*.txt'
находит в текущем каталоге (.
) и ниже все обычные файлы (-type f
), имена которых заканчиваются на.txt
|
передает вывод этой команды (список имен файлов) следующей командеxargs
собирает эти имена и передает их один за другимsed
sed -i '' -e 's/foo/bar/g'
означает «отредактировать файл на месте, без резервной копии, и выполнить следующую подстановку (s/foo/bar
) несколько раз в строке (/g
)» (см.man sed
)Обратите внимание, что часть «без резервной копии» в строке 4 подходит для меня, потому что файлы, которые я изменяю, в любом случае находятся под контролем версий, поэтому я могу легко отменить, если произошла ошибка.
источник
-print0
опции. Ваша команда не будет работать с файлами с пробелами и т.д. в их имени.find -name '*.txt' -exec sed -i 's/foo/bar/g' {} +
сделаю все это с помощью GNU find.sed: can't read : No such file or directory
когда я бегуfind . -name '*.md' -print0 | xargs -0 sed -i '' -e 's/ä/ä/g'
, ноfind . -name '*.md' -print0
дает список многих файлов.-i
''
''
после того,sed -i
какова''
роль?Это удаляет
xargs
зависимость.источник
sed
, поэтому не работает на большинстве систем. GNUsed
требует от вас не ставить пробел между-i
и''
.Если вы используете Git, вы можете сделать это:
-l
перечисляет только имена файлов.-z
печатает нулевой байт после каждого результата.Я закончил тем, что сделал это, потому что у некоторых файлов в проекте не было новой строки в конце файла, и sed добавил новую строку, даже когда это не сделало никаких других изменений. (Нет комментариев о том, должны ли файлы иметь перевод строки в конце. 🙂)
источник
find ... -print0 | xargs -0 sed ...
решения не только занимают больше времени, но и добавляют новые строки в файлы, у которых их еще нет, что создает неудобства при работе внутри git-репо.git grep
светится быстро по сравнениюВот моя функция zsh / perl, которую я использую для этого:
И я бы выполнил это с помощью
(например)
источник
Пытаться:
Проверено на Ubuntu 12.04.
Эта команда НЕ будет работать, если имена подкаталогов и / или имена файлов содержат пробелы, но если они у вас есть, не используйте эту команду, так как она не будет работать.
Обычно плохая практика - использовать пробелы в именах каталогов и именах файлов.
http://linuxcommand.org/lc3_lts0020.php
Посмотрите на "Важные факты об именах файлов"
источник
Используйте этот сценарий оболочки
Теперь я использую этот сценарий оболочки, который объединяет вещи, которые я узнал из других ответов и поиска в Интернете. Я поместил это в файл, названный
change
в папке на моем$PATH
и сделалchmod +x change
.источник
В моем случае я хотел заменить
foo:/Drive_Letter
наfoo:/bar/baz/xyz
В моем случае я смог сделать это с помощью следующего кода. Я был в той же папке, где было много файлов.надеюсь, что это помогло.
источник
Следующая команда отлично работала на Ubuntu и CentOS; Тем не менее, под OS XI постоянно получал ошибки:
Когда я пытался передать параметры через xargs, все работало без ошибок:
источник
-i
чтобы-i ''
, вероятно , более актуальным , чем тот факт , что вы изменили-exec
в-print0 | xargs -0
. Кстати, вам, вероятно, не нужно-e
.Вышеописанное работает как шарм, но со связанными каталогами, я должен добавить
-L
флаг к нему. Финальная версия выглядит так:источник