Следующая команда корректно изменяет содержимое 2 файлов.
sed -i 's/abc/xyz/g' xaa1 xab1
Но мне нужно динамически изменить несколько таких файлов, а я не знаю их имен. Я хочу написать команду, которая будет читать все файлы из текущего каталога, начиная с, xa*
и sed
должна изменить содержимое файла.
sed -i 's/abc/xyz/g' xa*
?Ответы:
Еще лучше:
потому что никто не знает, сколько файлов, и это легко нарушить ограничения командной строки.
Вот что происходит, когда файлов слишком много:
источник
for
команде. Чтобы защитить себя от этого, вы должны будете использоватьfind ... | xargs ...
for
чем дляecho
илиgrep
?"$i"
вместо того,$i
чтобы избежать разбиения слов в именах файлов с пробелами. В противном случае это очень приятно.for
является частью синтаксиса языка, а не просто встроенным. Посколькуsed -i 's/old/new' *
расширение*
ALL должно быть передано как arglist в sed, и я уверен, что это должно произойти еще до того, какsed
процесс может быть запущен. Используяfor
цикл, полный arglist (расширение*
) никогда не передается как команда, только сохраняется в памяти оболочки и повторяется. У меня нет никаких ссылок на это, хотя, просто кажется вероятным, что это разница. (Я хотел бы услышать от кого-то более знающего ...)Я удивлен, что никто не упомянул аргумент -exec для поиска, который предназначен для этого типа сценария использования, хотя он запускает процесс для каждого соответствующего имени файла:
В качестве альтернативы можно использовать xargs, который вызовет меньше процессов:
Или проще использовать
+
вариант exec вместо;
find, чтобы позволить find предоставить более одного файла на вызов подпроцесса:источник
find ./ -type f -name 'xa*' -exec sed -i '' 's/asd/dsg/g' {} \;
это расположение команды find./
и пара одинарных кавычек после-i
OSX../
равна.
и после-i
имеет только параметр backupsuffix.-exec
Вариант находки вместе с{} +
достаточно , чтобы решить эту проблему , как указано, и должна быть достаточно для большинства требований. Ноxargs
это лучший выбор в целом, потому что он также позволяет параллельную обработку с-p
опцией. Если расширение глобуса достаточно велико, чтобы переполнить длину командной строки, вы, вероятно, также выиграете от ускорения по сравнению с последовательным запуском.Вы можете использовать grep и sed вместе. Это позволяет рекурсивно искать в подкаталогах.
источник
grep -v
чтобы избежать мерзких папокgrep -rl <old> . | grep -v \.git | xargs sed -i 's/<old>/<new>/g'
Эти команды не будут работать по умолчанию,
sed
который поставляется с Mac OS X.От
man 1 sed
:Пытался
и
Оба работают нормально.
источник
@PaulR опубликовал это как комментарий, но люди должны рассматривать его как ответ (и этот ответ лучше всего подходит для моих нужд):
Это будет работать для небольшого количества файлов, возможно, порядка десятков, но, вероятно, не порядка миллионов .
источник
sed -i 's|auth-user-pass nordvpn.txt|auth-user-pass /etc/openvpn/nordvpn.txt|g' *.ovpn
.Еще один более универсальный способ заключается в использовании
find
:источник
Я использую
find
для аналогичной задачи. Это довольно просто: вы должны передать это в качестве аргумента дляsed
этого:sed -i 's/EXPRESSION/REPLACEMENT/g' `find -name "FILE.REGEX"`
Таким образом, вам не нужно писать сложные циклы, и просто увидеть, какие файлы вы собираетесь изменить, просто запустите
find
перед запускомsed
.источник
ты можешь сделать
' хххх ' текст, который вы ищете, и заменит его на ' yyyy '
источник
Если вы можете запустить скрипт, вот что я сделал для аналогичной ситуации:
Используя словарь / hashMap (ассоциативный массив) и переменные для
sed
команды, мы можем перебрать массив, чтобы заменить несколько строк. Включение в шаблон подстановочного знакаname_pattern
позволит заменить на месте файлы с шаблоном (это может быть что-то вродеname_pattern='File*.txt'
) в определенном каталоге (source_dir
). Все изменения написаныlogfile
вdestin_dir
Сначала объявляется массив пар, каждая пара является строкой замены, затем
WHAT1
будет заменена наFOR1
иOTHER_string_to replace
будет заменена наstring replaced
в файлеFile.txt
. В цикле считывается массив, первый член пары извлекается как,replace_what=$i
а второй какreplace_for=$j
. Командаfind
ищет в каталоге имя файла (которое может содержать подстановочный знак), иsed -i
команда заменяет те же файлы, которые были определены ранее. Наконец я добавилgrep
перенаправление в файл журнала, чтобы записать изменения, внесенные в файл (ы).Это сработало для меня
GNU Bash 4.3
sed 4.2.2
и основано на ответе VasyaNovikov для Loop over tuples in bash .источник