Intereting Posts
как извлечь часть текста из файла между согласованными условиями Где хранится страница пользователя tcl-doc? Преобразовать шрифт .bdf / .pcf в .psf (u) для использования в качестве consolefont? yum info: что означает «Репо: установлен»? возможно ли подключить мобильное приложение Android, Wi-Fi-маршрутизатор и устройство Wi-Fi? Системный файл CentOS 7 systemd (запустить скрипт python) работает, но регистрирует ошибки? настроить не добавлять символы продолжения строки в makefile Экспорт конфигураций NetworkManager Во вложенных каталогах извлекайте JPG из каждого кадра MP4, оставляя JPG в каталоге MP4 Операция перемещения файла над SAMBA сохраняет номер inode? Как управляются каталоги в файловой системе? Есть ли удобный способ обернуть список команд bash в rlwrap? Где я могу найти список кодов терминальных клавиш для переназначения ярлыков в bash? Изменен драйвер Nvidia xorg – теперь у меня меньше датчиков температуры? Вычисления даты без инструментов GNU

использование sed для замены строки в файлах, которые находятся в разных папках

У меня есть файл, который находится в разных папках (с расширением .mvw). Я хочу написать скрипт, который идет в каждую папку и заменить строку (в файле * .mvw) “D3PLOT_1DForce” на имя папки

Структура папок как ниже

  • XYZ_DV_L02_P01
  • XYZ_DV_L02_P02
  • XYZ_DV_L02_P03

Я написал следующий сценарий

#!/bin/sh for ii in XYZ_DV_L02* ; do (cd "$ii") find . -iname "*.mvw" -type f -exec sed -i "s/D3PLOT_1DForce_EffPlStrainMax_VonMisesMax/"${ii}"/g" "{}" \; done 

Он работает и заменяет строку именем папки, но заменяет имя 1-й папки во всех файлах. Я думаю, что sed не собирается в петле.

Как я могу поместить sed для работы в цикле, чтобы соответствующие имена папок использовались для замены строки в файле?

Команда cd выполняется в вложенной оболочке и поэтому фактически ничего не делает. Таким образом, ваша команда find выполняется из родительского каталога, по одному разу для каждого из имен XYZ_DV_L02* в XYZ_DV_L02* . Первый вызов sed изменяет строку во всех файлах, следующие вызовы sed не находят строку, но выполняются в любом случае.

Попробуй это:

 #!/bin/sh for ii in XYZ_DV_L02* ; do find "$ii" -iname "*.mvw" -type f -exec sed -i " s/D3PLOT_1DForce_EffPlStrainMax_VonMisesMax/${ii}/g" "{}" + done 

Спасибо за редактирование от Стефана Шазеля

Хотя я только что скопировал команду find из вопроса, только исправляя путь, стоит объяснить изменения:

  • ${ii} был заключен в кавычки, теперь он является частью кавычек, которые содержат весь аргумент sed .
  • Использование + вместо \; заставит find выполнить одну команду sed для нескольких файлов, а не одну для каждого файла.

редактировать

По запросу из комментария это заменит каждую последовательность набора [-_a-zA-Z0-9] за которой следует .h3d с текстом замены, который представляет собой имя файла, включая расширение .mvw , как я понимаю комментарий, но это не кажется полезным. Если вы хотите получить доступ к тексту в шаблоне, вы можете использовать \1 . Возможно, вам придется адаптировать набор для ваших конкретных потребностей.

 #!/bin/sh for ii in XYZ_DV_L02* ; do find "$ii" -iname "*.mvw" -type f -exec sed -i -r " s/([-_a-zA-Z0-9]+)\.h3d/${ii}.h3d/g" "{}" + done 

Попробуй это,

 #!/bin/sh for ii in XYZ_DV_L02* ; do cd "$ii" find . -iname "*.mvw" -type f -exec sed -i "s/D3PLOT_1DForce/"${ii}"/g" "{}" \; cd .. done 

Можно изменить каталог на первую входную папку для цикла for и поиска файла. Но мы должны вернуться в родительский каталог перед запуском следующего цикла.

Если у вас есть структура каталогов только с несколькими подкаталогами, у каждого из которых есть этот файл .mvw который вы хотите изменить, тогда вам не нужно использовать find потому что вы уже точно знаете, где находятся ваши файлы.

 for pathname in XYZ_DV_L02*/*.mvw; do sed -i "s/D3PLOT_1DForce/${pathname%%/*}/g" "$pathname" done 

Это перебирает все файлы .mvw в указанных подкаталогах и заменяет строку именем каталога. Расширение параметра ${pathname%%/*} удаляет все после первой строки / в строке в $pathname .

Тестирование:

 $ tree . |-- XYZ_DV_L02_P01 | `-- somefile.mvw |-- XYZ_DV_L02_P02 | `-- somefile.mvw `-- XYZ_DV_L02_P03 `-- somefile.mvw 3 directories, 3 files $ cat XYZ_DV_L02_P0*/*.mvw Hello D3PLOT_1DForce_EffPlStrainMax_VonMisesMax! Hello D3PLOT_1DForce_EffPlStrainMax_VonMisesMax! Hello D3PLOT_1DForce_EffPlStrainMax_VonMisesMax! 

(здесь работает цикл)

 $ cat XYZ_DV_L02_P0*/*.mvw Hello XYZ_DV_L02_P01_EffPlStrainMax_VonMisesMax! Hello XYZ_DV_L02_P02_EffPlStrainMax_VonMisesMax! Hello XYZ_DV_L02_P03_EffPlStrainMax_VonMisesMax! 

Очевидно, что если у вас есть глубокая иерархия, то вам, возможно, придется использовать find любом случае, но вы можете выполнять цикл изнутри find а не снаружи find :

 find XYZ_DV_L02*/ -type f -name '*.mvw' -exec sh -c ' for pathname do sed -i "s/D3PLOT_1DForce/${pathname%%/*}/g" "$pathname" done' sh {} + 

Здесь мы находим все файлы .mvw под любым из каталогов, соответствующих шаблону XYZ_DV_L02*/ . Для этих найденных файлов мы запускаем цикл, который делает то же самое, что и цикл в начале этого ответа. Это заменит строку D3PLOT_1DForce во всех файлах .mvw любом месте под любым из каталогов соответствующим XYZ_DV_L02* каталога XYZ_DV_L02* .

Связанные с:

  • Понимание опции -exec `find`

В этом ответе предполагается GNU sed или другая реализация sed которая выполняет редактирование на месте с -i без аргумента-опции.