Как сместить номера имен файлов без столкновений?

Рассмотрим этот список файлов:

$ touch index-{1,2,3,4,5,6,7,8,9}.txt 

Если я хочу сместить их так, чтобы они начинались с нуля, это относительно легко :

 $ rename --verbose 's/^index-([1-9])\.txt$/$1/; $_="index-" . ($_ - 1) . ".txt"' index-*.txt 

Это работает, потому что man bash указывает, что globs отсортированы по алфавиту, поэтому он переименует index-1.txt в index-0.txt перед переименованием index-2.txt в index-1.txt .

Это ломается, если вы хотите переместиться, или если номера имеют разную длину :

 $ touch index-{10,11}.txt $ rename --verbose 's/^index-([0-9]+)\.txt$/$1/; $_="index-" . ($_ + 1) . ".txt"' index-*.txt index-10.txt not renamed: index-11.txt already exists index-11.txt renamed as index-12.txt index-1.txt not renamed: index-2.txt already exists 

Возможные долгосрочные исправления:

  • rename параметр, чтобы попытаться изменить порядок операций до тех пор, пока не произойдет столкновений.
  • rename опцию сначала переместить файлы во временный каталог, а затем переместите их обратно с новым именем.
  • rename вариант переименования файлов в два этапа, используя уникальные имена на первом шаге, которые не будут сталкиваться с оригинальными или новыми именами.
  • Способ естественной сортировки + разворот шаров Bash.

Есть ли простой способ обойти это?

4 Solutions collect form web for “Как сместить номера имен файлов без столкновений?”

Решение @ l0b0's переписано для лучшей надежности:

 printf '%s\0' index-*.txt | sort --zero-terminated --field-separator - --key 2rn | xargs -0r rename --verbose ' s/^index-([0-9]+)\.txt$/$1/; $_="index-" . ($_ + 1) . ".txt"' 

Не стесняйтесь включать в свое решение, и после этого я удалю свой ответ.

Обратите внимание, что эти и @ l0bo решения являются специфичными для GNU, а не Unix (GNU's Un Unix).

В Unix есть небольшая известная стандартная команда, которая может помочь нам найти общее решение в поиске, в каком порядке должна быть выполнена серия переименований: tsort

Скажем, у нас есть список переименований, которые нужно сделать в файле renames.txt (предполагая, что для их демонстрации не должно быть пробелов):

 da ef be ac 

Поскольку d следует переименовать в a , это означает, что a необходимо переименовать до d . Таким образом, у нас есть частичный порядок сортировки, который будет обратным порядку переименования файлов.

tsort – это инструмент для вывода полного порядка сортировки из списка частичных заказов сортировки. Он вернется с ошибкой, если будет цикл, который поможет нам обнаружить случаи, когда нет решения. Если мы применим tsort на этом входе, это дает нам:

 b d e a f c 

Который говорит, что b следует переименовать после d после e . Мы можем использовать GNU tac (некоторые системы также имеют tail -r ), чтобы отменить этот порядок:

 c f a e d b 

И присоединитесь к нему с нашим списком переименований:

 tsort renames.txt | tac | awk ' NR==FNR { ren[$1] = $2 next } $1 in ren { print "mv -i --", $1, ren[$1] }' renames.txt - 

который дает нам:

 mv -i -- ac mv -i -- ef mv -i -- da mv -i -- be 

которые мы можем затем передать в sh для выполнения.

Обратите внимание, однако, что это не является надежным, поскольку мы не проверяем статус выхода tsort выше для обнаружения циклов, а имена файлов не должны содержать никаких специальных символов оболочки.

Роубилизация остается как упражнение для читателя 😉

Это работает для конкретного случая выше:

 rename --verbose 's/^index-([0-9]+)\.txt$/$1/; $_="index-" . ($_ + 1) . ".txt"' $(printf '%s\n' index-*.txt | sort --field-separator - --key 2n | tac) 

Но:

  1. он не обрабатывает пробелы в именах файлов и
  2. для произвольных имен файлов было бы намного сложнее.

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

 $ echo index-*.txt index-12.txt index-1.txt index-2.txt index-4.txt $ echo index-*.txt(n) index-1.txt index-2.txt index-4.txt index-12.txt $ echo index-*.txt(nOn) index-12.txt index-4.txt index-2.txt index-1.txt 

Или вы можете определить свой собственный порядок сортировки с помощью функции и использовать index-*(o+that-function) .

Также обратите внимание, что zsh имеет собственную встроенную функцию rename zmv :

 $ zmv -fvQ 'index-(<->).txt(n)' 'index-$(($1-1)).txt' mv -- index-1.txt index-0.txt mv -- index-2.txt index-1.txt mv -- index-4.txt index-3.txt mv -- index-12.txt index-11.txt $ zmv -fvQ 'index-(<->).txt(nOn)' 'index-$(($1+1)).txt' mv -- index-11.txt index-12.txt mv -- index-3.txt index-4.txt mv -- index-1.txt index-2.txt mv -- index-0.txt index-1.txt 
  • Как сортировать файлы по части имени файла?
  • Как можно сортировать поле CPU команды ps?
  • Чтение каталога в сценарии оболочки
  • Как я могу перечислить файлы по классу / индикатору (как в ls -classify), а затем по имени?
  • Как отсортировать по 2 столбцам и сохранить верхнюю строку из каждой группы?
  • как получить последний файл в каждом каталоге
  • Как распечатать пять самых высоких чисел из столбца?
  • Удаление дубликатов в большом текстовом списке
  • Эффективное объединение / сортировка / уникальное большое количество текстовых файлов
  • сортировка имен файлов численно, когда у них есть нечисловой префикс
  • Есть ли способ сортировать grep-вывод csv-файла?
  • Interesting Posts

    Требует ли CVE 2006-7098 доступа (входящего в систему) к уязвимому Debian?

    uboot написать ядро ​​в mmc раздел

    Кнопки Windows FVWM (Maximize Minimize …), Темы

    Что означает флаг «барьер» в Linux?

    Как проверить, есть ли в нем символы?

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

    Убейте отключенный сеанс SSH, запущенный в `screen`

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

    У меня есть тысячи попыток пробить мою систему в этом журнале из журнала?

    Как связать несколько команд tmux с одним нажатием клавиши?

    Quagga перестала работать после обновлений в Stretch

    Скрипт для вставки строки в файлы в поддиректории

    mdadm не автомонтирует диски raid0 под / media / storage

    Как проверить, включен ли Wi-Fi в режиме Hotspot (AP)

    Программный центр Ubunutu не работает, показывая черный экран

    Linux и Unix - лучшая ОС в мире.