переименовать конец имени файла, вычитая значение - PullRequest
1 голос
/ 28 апреля 2019

У меня в macOS следующие файлы в каталоге ns_up /:

sqRatio_ist_LogSplineInterpPk_iz_260.dat
sqRatio_ist_LogSplineInterpPk_iz_261.dat
sqRatio_ist_LogSplineInterpPk_iz_262.dat
sqRatio_ist_LogSplineInterpPk_iz_263.dat
sqRatio_ist_LogSplineInterpPk_iz_264.dat
sqRatio_ist_LogSplineInterpPk_iz_265.dat
sqRatio_ist_LogSplineInterpPk_iz_266.dat
sqRatio_ist_LogSplineInterpPk_iz_267.dat
sqRatio_ist_LogSplineInterpPk_iz_268.dat
sqRatio_ist_LogSplineInterpPk_iz_269.dat
sqRatio_ist_LogSplineInterpPk_iz_270.dat
sqRatio_ist_LogSplineInterpPk_iz_271.dat
sqRatio_ist_LogSplineInterpPk_iz_272.dat
sqRatio_ist_LogSplineInterpPk_iz_273.dat
sqRatio_ist_LogSplineInterpPk_iz_274.dat
sqRatio_ist_LogSplineInterpPk_iz_275.dat
sqRatio_ist_LogSplineInterpPk_iz_276.dat
sqRatio_ist_LogSplineInterpPk_iz_277.dat
sqRatio_ist_LogSplineInterpPk_iz_278.dat
sqRatio_ist_LogSplineInterpPk_iz_279.dat
sqRatio_ist_LogSplineInterpPk_iz_280.dat
sqRatio_ist_LogSplineInterpPk_iz_281.dat
sqRatio_ist_LogSplineInterpPk_iz_282.dat
sqRatio_ist_LogSplineInterpPk_iz_283.dat
sqRatio_ist_LogSplineInterpPk_iz_284.dat
sqRatio_ist_LogSplineInterpPk_iz_285.dat
sqRatio_ist_LogSplineInterpPk_iz_286.dat
sqRatio_ist_LogSplineInterpPk_iz_287.dat
sqRatio_ist_LogSplineInterpPk_iz_288.dat
sqRatio_ist_LogSplineInterpPk_iz_289.dat
sqRatio_ist_LogSplineInterpPk_iz_290.dat
sqRatio_ist_LogSplineInterpPk_iz_291.dat
sqRatio_ist_LogSplineInterpPk_iz_292.dat
sqRatio_ist_LogSplineInterpPk_iz_293.dat
sqRatio_ist_LogSplineInterpPk_iz_294.dat
sqRatio_ist_LogSplineInterpPk_iz_295.dat
sqRatio_ist_LogSplineInterpPk_iz_296.dat
sqRatio_ist_LogSplineInterpPk_iz_297.dat
sqRatio_ist_LogSplineInterpPk_iz_298.dat
sqRatio_ist_LogSplineInterpPk_iz_299.dat

Я бы хотел переименовать каждый из них, вычтя значение 200 в конце имени файла, например:

sqRatio_ist_LogSplineInterpPk_iz_299.dat = sqRatio_ist_LogSplineInterpPk_iz_99.dat

Я попробовал следующее:

for i in $(ls ns_up/); do
  number=$(echo $i | gsed 's/\(.*\)_\(.*\).dat/\2/')
  new_number=$((number-200))
  echo $i | gsed 's/_\(.*\)\.dat/"\$new_number"\.dat/'
done

Но, к сожалению, это не работает, и я не знаю, почему.

1012 * У кого-нибудь была бы идея?

Ответы [ 5 ]

3 голосов
/ 28 апреля 2019

Вы можете установить (Perl) rename с homebrew , используя:

brew install rename

Тогда попробуйте:

rename -n 's/(\d+)/$1 - 200/e' ns_up/*dat

-n говорит сделать "пробный прогон" , то есть сказать, что он будет делать, фактически ничего не делая.

Выражение Perl в одинарных кавычках получает каждое имя файла по очереди в переменной $_ и, как ожидается, изменит его и вернет новое значение в той же переменной.

Подстановка гласит: «замените любой набор соседних цифр, который он найдет, этим числом минус 200».

e говорит оценить правую сторону замещения.

Этот подход имеет некоторые дополнительные преимущества:

  • Вы можете легко выполнить пробежку
  • он не будет закрывать файлы, если любые два входных имени файла приводят к одному и тому же выходному имени файла
  • см. Справочную страницу для многих других преимуществ
1 голос
/ 29 апреля 2019

Это может работать для вас (параллельно GNU):

parallel --dryrun mv {} '{= s/\d+/& - 200/e =}' ::: *.dat

Удалите параметр --dryrun после проверки сгенерированных команд.

1 голос
/ 28 апреля 2019

Это, вероятно, то, что вы пытаетесь сделать (используя bash для арифметической операции BASH_REMATCH [] и $ ((..))):

for old in ns_up/*.dat; do
    [[ $old =~ ^(.*)_(.*)(\.dat)$ ]] || { printf 'Warning, unexpected old file name format "%s"\n' "$old" >&2; continue; }
    new="${BASH_REMATCH[1]}$((${BASH_REMATCH[2]}-200))${BASH_REMATCH[3]}"
    [[ -f "$new" ]] && { printf 'Warning, new file name "%s" generated from "%s" already exists, skipping.\n' "$new" "$old" >&2; continue; }
    mv -- "$old" "$new"
done

Вам нужен этот тест для новых, уже существующих сновое имя файла может совпадать с существующим, и вы, вероятно, не хотите его перезаписывать.

0 голосов
/ 28 апреля 2019

Проблема с вашей командой в том, что у вас нет команды mv, и вы не вычисляете левую часть нового имени файла.Это работает:

▶ for i in ns_up/* ; do
    n=$(echo "$i" | gsed -E 's/(.*)_([0-9]+).dat/\2/')
    new_n=$((n - 200))
    left=$(echo "$i" | gsed -E 's/[0-9]+.*//')
    mv -i "$i" "$left${new_n}.dat"
  done

Примечания:

  • Я указал mv -i для защиты от случайной перезаписи файла.

  • Я использовал -E для команды sed для использования расширенных регулярных выражений, что позволяет использовать более понятный синтаксис.

  • Я использовал gsed -E 's/(.*)_([0-9]+).dat/\2/' вместо вашего gsed 's/\(.*\)_\(.*\).dat/\2/', потому что соответствовал[0-9]+ (число) явно яснее и точнее о том, какое подчеркивание вы подходите.

0 голосов
/ 28 апреля 2019

попробовал на GNU SED:

   find . -iregex '.+sqRatio_ist_LogSplineInterpPk_iz_2[0-9]+\.dat' -exec sh -c 'mv {} `echo {}|sed -E "s/(.+_)2([0-9]+\.dat)/\1\2/"`' \;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...