Переименовать несколько файлов, чтобы уменьшить номер в имени файла?

Переименовать несколько файлов, чтобы уменьшить номер в имени файла?

У меня неправильно названы файлы, которые не синхронизированы -1. Проблема в том, что мне нужно переименовать 1000 из них.

  • DBGC180_805754
  • DBGC180_805755
  • DBGC180_805756

к

  • DBGC180_805753
  • DBGC180_805754
  • DBGC180_805755

Я бы предпочел использовать скрипты bash или команды unix.

решение1

Вы можете сделать это:

# {smallestfilenum..largestfilenum}

for i in {805754..999999}; do 
   mv "DBGC180_$i" "DBGC180_$(($i-1))";
done

Попробуйте с небольшим числом (например, 805754..805758), чтобы убедиться, что это работает так, как вы ожидаете. Имейте в виду, что если файл с новым именем уже существует, он будет перезаписан.

решение2

  1. Переместите файлы, которые необходимо переименовать, в подкаталог (не меняя их имени).
  2. Переименуйте файлы из подкаталога в исходный каталог.

Есть две причины, по которым я рекомендую шаг 1, даже если без него можно обойтись:

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

Непроверенный фрагмент оболочки (полагающийся на тот факт, что уменьшаемое число никогда не имеет начальных нулей):

mkdir to_decrement
for x in DBGC180_80575[4-9] DBGC180_8057[6-9]? DBGC180_805[8-9]?? DBGC180_80[6-9]??? DBGC180_8[1-9]???? DBGC180_9?????; do
  mv "$x" to_decrement/
done
cd to_decrement
for x in *; do
  number="${x##*_}"
  mv -i -- "$x" "../${x%_*}_$((number-1))"
done
cd ..
rmdir to_decrement

Сзш, вы можете сделать это намного проще, благодаря егочисловой диапазон glob, еговстроенныйmvчто позволяет избежать ограничений на длину командной строки, и егофункция массового переименования на основе шаблона. В зш:

autoload -U zmv
zmodload -m -F zsh/files b:zf_\*
mkdir to_decrement
zf_mv DBGC180_<805754-> to_decrement/
zmv 'to_decrement/(*)_(*)' '${1}_$(($2-1))'
rmdir to_decrement

решение3

Итак, вы хотите переименовать DBGC180_805754в DBGC180_805753, ...55в ...54и т. д. Это проблема, которую я решу.

Сначала поместите этот скрипт куда-нибудь в свой PATH, назовите его waltinator.

#!/bin/bash
#step through the parameters 
while [[ -n "$1" ]] ; do
    oldname="$1"
    # shift the arguments left
    shift;
    # strip off the fixed part of the old name
    oldnum=${oldname##DBGC180_}
    # decrement the number (this is what was wanted, right?)
    newnum=$(( $oldnum - 1 ))
    # build the new, improved filename
    newname="DBGC180_$newnum"
    if [[ -f "$newname" ]] ; then
        printf "Cannot rename $oldname to $newname, $newname exists.\n" >&2
        exit 1
    fi
    mv --no-clobber "$oldname" "$newname"
done
exit 0

Для следующего шага предположим, что скрипт находится в $HOME/bin/waltinator, и у вас есть chmod +x $HOME/bin/waltinator.

find . -type f -name 'BDGC180_[0-9][0-9][0-9][0-9][0-9][0-9]` -print | \
    sort | \
    xargs $HOME/bin/waltinator

Находит findфайлы (в произвольном порядке), имена которых соответствуют шаблону shell glob " BDGC180_с последующими 6 цифрами ( ). Поскольку нам нужен отсортированный список (переименование в до переименования [0-9]было бы ошибкой ), мы запускаем вывод через . Затем мы используем , чтобы взять (отсортированный) список имен файлов, и создаем команду для передачи (отсортированного) списка имен файлов в . Прочтите, если вам нужно сократить список аргументов....97...96...96findsortxargs$HOME/bin/waltinatorman xargs

Если на то пошло, прочтите:

for page in bash mv find sort xargs ; do
    man "$page"
done   

решение4

Используйте renameдля замены каждого числа самим собой минус 1.

$ rename -v 's/\d{6}/sprintf("%06",($&-1))/e'    

Примечания

  • renameиспользует выражения Perl для переименования имен файлов.
  • sуказывает, что renameбудут заменены некоторые или все имена файлов, соответствующие шаблону регулярного выражения.
  • Выражения подстановки Perl структурированы следующим образом.
    • s/PATTERN/REPLACEMENT/MODIFIER
  • \d{6}это шаблон, который renameбудет искать и заменять. Это 6 десятичных цифр.
  • $— это переменная, хранящая совпавшую подстроку \d{6}(в данном случае «подстрока» — это целое число).
  • sprintf("%06",($&-1))извлекает значение, хранящееся в $, уменьшает его, затем возвращает это значение в качестве замены. %06Для обработки начальных нулей.
  • eуказано, что renameзамена оценивается так, как если бы это был оператор Perl, и в качестве текста замены используется возвращаемое значение.
  • -vзаставляет renameэхом отражать то, что он делает.

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

Похоже, это работает только для уменьшения, поэтому будьте осторожны.

Связанный контент