Как добавить чередующиеся строки к именам файлов и перенумеровать их попарно?

Чтобы завершить решение:

Чтобы отключить глубокий сон в BIOS X1,

перезагрузите X1 нажмите F12 сразу после запуска, чтобы войти в BIOS, нажмите «Tab», чтобы выбрать «Приложение «Меню» нажмите «Ввод», чтобы войти в «Настройка», нажмите →, чтобы выбрать «Конфигурация», нажмите ↓, пока не дойдете до «Питание», затем нажмите «Ввод», пока не дойдете до «Технологии быстрого запуска Intel (R)» нажмите «Ввод», чтобы переключить его на «Отключено», наконец, нажмите F10, чтобы сохранить и выйти
7
задан 28 September 2017 в 23:24

5 ответов

Я использовал способ сделать это в Bash на основе идеи, что если число в имени файла четное, мы хотим разделить его на два и добавить c2, а если число нечетное, мы хотим добавьте один к нему, а затем разделите на два и добавьте c1. Рассмотрение нечетных и четных файлов, подобных этому, намного длиннее, чем метод Бейша Элиа Кагана, и я согласен с тем, что использование rename, как и в этом другом ответе Элиа Кагана, является разумным способом, но такой подход может быть полезен в некоторых ситуациях.

Небольшое преимущество этого, используя диапазон, подобный {0000...0012}, заключается в том, что он пытается работать только с существующими файлами, поэтому он не будет жаловаться, если файлы не существуют. Тем не менее, вы все равно получаете нелогично пронумерованные файлы, если есть пробелы. См. Вторую часть моего ответа для способа, который не имеет этой проблемы.

В одной строке это выглядит ужасно:

for f in *; do g="${f%.tif}"; h="${g#ome}"; if [[ $(bc <<< "$h%2") == 0 ]]; then printf -v new "ome%04dc2.tif" "$(bc <<< "$h/2")" ; echo mv -vn -- "$f" "$new"; else printf -v new "ome%04dc1.tif" "$(bc <<< "($h+1)/2")"; echo mv -vn -- "$f" "$new"; fi; done

Вот это как скрипт:

#!/bin/bash

for f in *; do 
    g="${f%.tif}"
    h="${g#ome}"

    if [[ $(bc <<< "$h%2") == 0 ]]; then 
         printf -v new "ome%04dc2.tif" "$(bc <<< "$h/2")"
         echo mv -vn -- "$f" "$new"
    else
         printf -v new "ome%04dc1.tif" "$(bc <<< "($h+1)/2")"
         echo mv -vn -- "$f" "$new"
    fi
done

Операторы echo, предваряющие mv, предназначены только для тестирования.

Примечания

g="${f%.tif}"     # strip off the extension
h="${g#ome}"      # strip off the letters... now h contains the number

Проверьте, что число четное (т.е. деление на 2 не дает никакого остатка) )

if [[ $(bc <<< "$h%2") == 0 ]]; then 

Я использовал bc, который не будет пытаться обрабатывать числа с ведущими нулями в виде восьмеричных чисел, хотя я мог бы просто отключить нули с другим расширением строки, (! d9]

Далее постройте новое имя для файлов с четным номером:

printf -v new "ome%04dc2.tif" "$(bc <<< "$h/2")"

%04d будет заменен на числовой вывод

Переименуйте исходный файл с построенным новым именем

echo mv -vn -- "$f" "$new"

-v для verbose, -n для no-clobber (не перезаписывайте файлы, у которых уже есть предполагаемое имя, если они существуют) и --, чтобы предотвратить ошибки с именами файлов, начинающимися с - (но поскольку остальная часть моего сценария ожидает, что ваши файлы будут называться ome[somenumber].tif Я думаю, я просто добавляю его из h abit).

Заполнение пробелов

После некоторой обработки и дополнительной помощи от Элиа Кагана я разработал более лаконичный способ увеличить имена, которые имеют преимущество заполнения пробелов. Проблема заключается в том, что только увеличивает число, выполняет некоторую простую арифметику по этому номеру, форматирует его и помещает в имя файла. Баш думает (так сказать) «ОК, вот следующий файл, я дам ему следующее имя», не обращая внимания на исходное имя файла. Это означает, что он создает новые имена, которые не относятся к старым именам, поэтому вы не сможете логически отменить переименование, и файлы будут переименованы в правильном порядке, только если их имена уже будут такими, что они будут обработаны в правильном порядке. Это имеет место в вашем примере, который имеет номера с нулевой шириной с фиксированной шириной, но если бы у вас были файлы с именами, скажем, 2, 8, 10, 45, они обрабатывались в порядке [ f30], 2, 45, 8, что, вероятно, не то, что вы хотите.

Если этот подход подходит для вас, учитывая все это, вы можете сделать это следующим образом:

i=0; for f in ome????.tif; do ((i++)); printf -v new "ome%04dc%d.tif" $(((i+1)/2)) $(((i+1)%2+1)); echo mv -vn "$f" "$new"; done 

или

#!/bin/bash
i=0

for f in ome????.tif; do 
    ((i++))
    printf -v new "ome%04dc%d.tif" $(((i+1)/2)) $(((i+1)%2+1))
    echo mv -vn "$f" "$new"
done 

Примечания [!d20 ] i=0 инициировать переменную ((i++)) увеличивать переменную на единицу (это подсчитывает итерации цикла) printf -v new поставить следующий оператор в переменную new "ome%04dc%d.tif" новое имя файла с числовыми форматами, которые будет заменено на последующие упомянутые числа $(((i+1)/2)) количество раз, когда цикл был запущен плюс один, разделенный на 2. Это работает на том основании, что Bash выполняет только целочисленное деление, поэтому, когда мы делим нечетное число на 2, получаем тот же ответ, который мы получили, когда мы разделили предыдущее четное число на 2:
$ echo $((2/2))
1
$ echo $((3/2))
1
$(((i+1)%2+1)) Остаток после деления количества циклов, которые были запущены плюс один за другим, плюс один. Это означает, что если число итераций нечетное (например, первый прогон), выход будет 1, и если номер итерации четный (например, второй прогон), выход будет 2, давая [ f43] или c2 я использовал i=0, потому что тогда в любой момент во время прогона значение i будет числом циклов, которые были бы запущены, что может быть полезно для отладки, так как это также будет порядковый номер обрабатываемого файла (т. е. когда i=69 мы обрабатываем 69-й файл). Однако мы можем упростить арифметику, начиная с другого i, например:
i=2; for f in ome????.tif; do printf -v new "ome%04dc%d.tif" $((i/2)) $((i%2+1)); echo mv -vn "$f" "$new"; ((i++)); done 
Существует много способов сделать это :) echo только для тестирования - удалите, если вы видите нужный результат.

Вот пример того, что делает этот метод:

$ ls
ome0002.tif  ome0004.tif  ome0007.tif  ome0009.tif  ome0010.tif  ome0012.tif  ome0019.tif  ome0100.tif  ome2996.tif
$ i=0; for f in ome????.tif; do ((i++)); printf -v new "ome%04dc%d.tif" $(((i+1)/2)) $(((i+1)%2+1)); echo mv -vn "$f" "$new"; done 
mv -vn ome0002.tif ome0001c1.tif
mv -vn ome0004.tif ome0001c2.tif
mv -vn ome0007.tif ome0002c1.tif
mv -vn ome0009.tif ome0002c2.tif
mv -vn ome0010.tif ome0003c1.tif
mv -vn ome0012.tif ome0003c2.tif
mv -vn ome0019.tif ome0004c1.tif
mv -vn ome0100.tif ome0004c2.tif
mv -vn ome2996.tif ome0005c1.tif

6
ответ дан 22 May 2018 в 18:02

Вы можете написать цикл оболочки для этого, если вы действительно этого хотите.

Если вы хотите, чтобы команда, которая работает в системах, которые не имеют rename или чья rename команда не prename, или вы хотите, чтобы его несколько легче поняли люди, которые знают Bash, но не Perl, или по какой-либо другой причине вы хотите реализовать это как цикл в своей оболочке, который вызывает команду mv, вы можете. (В противном случае я рекомендую метод rename в моем другом ответе на это.)

Ubuntu имеет Bash 4, в котором mv сохраняет начальные нули, поэтому {0001..0012} расширяется до 0001 0002 0003 0004 0005 0006 0007 0008 0009 0010 0011 0012. Это подходит только в ситуациях, когда у вас есть все файлы в диапазоне. Основываясь на описании проблемы в вашем вопросе, похоже, это так. В противном случае он все равно будет работать, но вы получите целую кучу сообщений об ошибках для разрывов, что затруднит обнаружение каких-либо других ошибок, которые могут быть действительно важны. Замените 0012 вашей фактической верхней границей.

Поскольку перед mv появляется echo, эта команда просто печатает команды mv, которые будут выполняться, без фактического запуска: 1 [!d9 ]

for i in {0001..0012}; do echo mv -n "ome$i.tif" "$(printf 'ome%04dc%d.tif' "$(((10#$i - 1) / 2 + 1))" "$((2 - 10#$i % 2))")"; done

Это использует ту же основную идею, что и в echo , как по мере прохождения арифметики, так и по значению %04d и %d в строках формата , Это можно сделать с помощью {1..12}, но тогда это было бы еще более сложным, потому что для замены двух $( ) команд вместо printf потребовалось бы printf.

Пожалуйста, держите что -n в rename -n не означает то же, что и -n в mv -n. Запуск rename -n не перемещает файлы вообще. Запуск mv -n перемещает файлы, если для этого не потребуется переписывать существующий файл в пункте назначения, что означает, что mv -n дает вам безопасность, которую вы автоматически получаете с помощью rename (если вы не запустите rename -f ). Это применимо только в ситуациях, когда у вас есть все файлы в диапазоне. :

for i in {0001..0012}; do mv -n "ome$i.tif" "$(printf 'ome%04dc%d.tif' "$(((10#$i - 1) / 2 + 1))" "$((2 - 10#$i % 2))")"; done

Вот как работает эта петля Bash:

for i in {0001..0012} выполняет команды после do двенадцать раз, при этом i принимает другое значение каждый раз. У этого цикла только одна такая команда перед done, что означает конец тела цикла. (Концептуально, когда элемент управления попадает на done, он переходит к следующей итерации цикла, а i - как следующее значение.) Эта одна команда:

mv -n "ome$i.tif" "$(printf 'ome%04dc%d.tif' "$(((10#$i - 1) / 2 + 1))" "$((2 - 10#$i % 2))")"
$i появляется несколько раз в цикле. Это расширение параметра, и оно заменяется текущим значением i. ome$i.tif расширяется до одного из ome0001.tif, ome0002.tif, ome0003.tif и т. д., в зависимости от того, какое значение имеет значение i. Включение ведущих 0s путем записи {0001..0012} вместо {1..12} делает этот аргумент mv, который дает старое имя файла, простое для записи. $( ) - подстановка команд. Внутри я запускаю команду printf, которая выводит желаемый текст второго аргумента на mv, который дает новое имя файла. Все это заключено в цитатах " ", поэтому избегают нежелательных расширений, в частности, глобирования и разбиения слов. При подстановке команд $(...) заменяется выходом, созданным при запуске команды ....

Команда, которая выводит имя файла назначения, такова:

printf 'ome%04dc%d.tif' "$(((10#$i - 1) / 2 + 1))" "$((2 - 10#$i % 2))"
$i появляется несколько раз в цикле. Это расширение параметра, и оно заменяется текущим значением i. Для выполнения вычислений каждый из двух аргументов использует расширение параметра . Весь $((...)) заменяется результатом вычисления выражения .... ome$i.tif расширяется до одного из ome0001.tif, ome0002.tif, ome0003.tif и т. д., в зависимости от того, какое значение имеет значение i. Включение начальных 0s путем записи {0001..0012} вместо {1..12} делает этот аргумент mv, который дает старое имя файла, простое для записи. Арифметика здесь такая же, как я использовал из [ f76], за исключением того, что деление в Bash автоматически является целым делением - оно автоматически обрезает дробную часть, поэтому нет необходимости использовать что-либо, соответствующее функции int Perl.

1 Ошибка выделения синтаксиса, используемого для кода Bash на этом сайте, в настоящее время вызывает все, после того, как # будет недоступен. Некорректный # обычно запускает комментарий в Bash, хотя в этом случае это не так. Вам не нужно беспокоиться об этом - ваш интерпретатор Bash не будет делать ту же ошибку.

1 Ошибка подсветки синтаксиса, используемая для кода Bash на этом сайте в настоящее время вызывает все после того, как # будет недоступен. Некорректный # обычно запускает комментарий в Bash, хотя в этом случае это не так. Вам не нужно беспокоиться об этом - ваш интерпретатор Bash не допустит ошибку.

5
ответ дан 22 May 2018 в 18:02

Я использовал способ сделать это в Bash на основе идеи, что если число в имени файла четное, мы хотим разделить его на два и добавить c2, а если число нечетное, мы хотим добавьте один к нему, а затем разделите на два и добавьте c1. Рассмотрение нечетных и четных файлов, подобных этому, намного длиннее, чем метод Бейша Элиа Кагана, и я согласен с тем, что использование rename, как и в этом другом ответе Элиа Кагана, является разумным способом, но такой подход может быть полезен в некоторых ситуациях.

Небольшое преимущество этого, используя диапазон, подобный {0000...0012}, заключается в том, что он пытается работать только с существующими файлами, поэтому он не будет жаловаться, если файлы не существуют. Тем не менее, вы все равно получаете нелогично пронумерованные файлы, если есть пробелы. См. Вторую часть моего ответа для способа, который не имеет этой проблемы.

В одной строке это выглядит ужасно:

for f in *; do g="${f%.tif}"; h="${g#ome}"; if [[ $(bc <<< "$h%2") == 0 ]]; then printf -v new "ome%04dc2.tif" "$(bc <<< "$h/2")" ; echo mv -vn -- "$f" "$new"; else printf -v new "ome%04dc1.tif" "$(bc <<< "($h+1)/2")"; echo mv -vn -- "$f" "$new"; fi; done

Вот это как скрипт:

#!/bin/bash for f in *; do g="${f%.tif}" h="${g#ome}" if [[ $(bc <<< "$h%2") == 0 ]]; then printf -v new "ome%04dc2.tif" "$(bc <<< "$h/2")" echo mv -vn -- "$f" "$new" else printf -v new "ome%04dc1.tif" "$(bc <<< "($h+1)/2")" echo mv -vn -- "$f" "$new" fi done

Операторы echo, предваряющие mv, предназначены только для тестирования.

Примечания

g="${f%.tif}" # strip off the extension h="${g#ome}" # strip off the letters... now h contains the number

Проверьте, что число четное (т.е. деление на 2 не дает никакого остатка) )

if [[ $(bc <<< "$h%2") == 0 ]]; then

Я использовал bc, который не будет пытаться обрабатывать числа с ведущими нулями в виде восьмеричных чисел, хотя я мог бы просто отключить нули с другим расширением строки, (! d9]

Далее постройте новое имя для файлов с четным номером:

printf -v new "ome%04dc2.tif" "$(bc <<< "$h/2")"

%04d будет заменен на числовой вывод

Переименуйте исходный файл с построенным новым именем

echo mv -vn -- "$f" "$new"

-v для verbose, -n для no-clobber (не перезаписывайте файлы, у которых уже есть предполагаемое имя, если они существуют) и --, чтобы предотвратить ошибки с именами файлов, начинающимися с - (но поскольку остальная часть моего сценария ожидает, что ваши файлы будут называться ome[somenumber].tif Я думаю, я просто добавляю его из h abit).

Заполнение пробелов

После некоторой обработки и дополнительной помощи от Элиа Кагана я разработал более лаконичный способ увеличить имена, которые имеют преимущество заполнения пробелов. Проблема заключается в том, что только увеличивает число, выполняет некоторую простую арифметику по этому номеру, форматирует его и помещает в имя файла. Баш думает (так сказать) «ОК, вот следующий файл, я дам ему следующее имя», не обращая внимания на исходное имя файла. Это означает, что он создает новые имена, которые не относятся к старым именам, поэтому вы не сможете логически отменить переименование, и файлы будут переименованы в правильном порядке, только если их имена уже будут такими, что они будут обработаны в правильном порядке. Это имеет место в вашем примере, который имеет номера с нулевой шириной с фиксированной шириной, но если бы у вас были файлы с именами, скажем, 2, 8, 10, 45, они обрабатывались в порядке 10, 2, 45, 8, что, вероятно, не то, что вы хотите.

Если этот подход подходит для вас, учитывая все это, вы можете сделать это следующим образом:

i=0; for f in ome????.tif; do ((i++)); printf -v new "ome%04dc%d.tif" $(((i+1)/2)) $(((i+1)%2+1)); echo mv -vn "$f" "$new"; done

или

#!/bin/bash i=0 for f in ome????.tif; do ((i++)) printf -v new "ome%04dc%d.tif" $(((i+1)/2)) $(((i+1)%2+1)) echo mv -vn "$f" "$new" done

Примечания

i=0 инициировать переменную ((i++)) увеличивать переменную на единицу (это подсчитывает итерации цикла) printf -v new поставить следующий оператор в переменную new "ome%04dc%d.tif" новое имя файла с числовыми форматами, которые будет заменено на последующие упомянутые числа $(((i+1)/2)) количество раз, когда цикл был запущен плюс один, разделенный на 2. Это работает на том основании, что Bash выполняет только целочисленное деление, поэтому, когда мы делим нечетное число на 2, получаем тот же ответ, который мы получили, когда мы разделили предыдущее четное число на 2: $ echo $((2/2)) 1 $ echo $((3/2)) 1 $(((i+1)%2+1)) Остаток после деления количества циклов, которые были запущены плюс один за другим, плюс один. Это означает, что если число итераций нечетное (например, первый прогон), выход будет 1, и если номер итерации четный (например, второй прогон), выход будет 2, давая c1 или c2 я использовал i=0, потому что тогда в любой момент во время прогона значение i будет числом циклов, которые были бы запущены, что может быть полезно для отладки, так как это также будет порядковый номер обрабатываемого файла (т. е. когда i=69 мы обрабатываем 69-й файл). Однако мы можем упростить арифметику, начиная с другого i, например: i=2; for f in ome????.tif; do printf -v new "ome%04dc%d.tif" $((i/2)) $((i%2+1)); echo mv -vn "$f" "$new"; ((i++)); done Существует много способов сделать это :) echo только для тестирования - удалите, если вы видите нужный результат.

Вот пример того, что делает этот метод:

$ ls ome0002.tif ome0004.tif ome0007.tif ome0009.tif ome0010.tif ome0012.tif ome0019.tif ome0100.tif ome2996.tif $ i=0; for f in ome????.tif; do ((i++)); printf -v new "ome%04dc%d.tif" $(((i+1)/2)) $(((i+1)%2+1)); echo mv -vn "$f" "$new"; done mv -vn ome0002.tif ome0001c1.tif mv -vn ome0004.tif ome0001c2.tif mv -vn ome0007.tif ome0002c1.tif mv -vn ome0009.tif ome0002c2.tif mv -vn ome0010.tif ome0003c1.tif mv -vn ome0012.tif ome0003c2.tif mv -vn ome0019.tif ome0004c1.tif mv -vn ome0100.tif ome0004c2.tif mv -vn ome2996.tif ome0005c1.tif
6
ответ дан 18 July 2018 в 06:05

Вы можете написать цикл оболочки для этого, если вы действительно этого хотите.

Если вы хотите, чтобы команда, которая работает в системах, которые не имеют rename или чья rename команда не prename, или вы хотите, чтобы его несколько легче поняли люди, которые знают Bash, но не Perl, или по какой-либо другой причине вы хотите реализовать это как цикл в своей оболочке, который вызывает команду mv, вы можете. (В противном случае я рекомендую метод rename в моем другом ответе на это.)

Ubuntu имеет Bash 4, в котором mv сохраняет начальные нули, поэтому {0001..0012} расширяется до 0001 0002 0003 0004 0005 0006 0007 0008 0009 0010 0011 0012. Это подходит только в ситуациях, когда у вас есть все файлы в диапазоне. Основываясь на описании проблемы в вашем вопросе, похоже, это так. В противном случае он все равно будет работать, но вы получите целую кучу сообщений об ошибках для разрывов, что затруднит обнаружение каких-либо других ошибок, которые могут быть действительно важны. Замените 0012 вашей фактической верхней границей.

Поскольку перед mv появляется echo, эта команда просто печатает команды mv, которые будут выполняться, без фактического запуска: 1

for i in {0001..0012}; do echo mv -n "ome$i.tif" "$(printf 'ome%04dc%d.tif' "$(((10#$i - 1) / 2 + 1))" "$((2 - 10#$i % 2))")"; done

Это использует ту же основную идею, что и в echo , как по мере прохождения арифметики, так и по значению %04d и %d в строках формата , Это можно сделать с помощью {1..12}, но тогда это было бы еще более сложным, потому что для замены двух $( ) команд вместо printf потребовалось бы printf.

Пожалуйста, держите что -n в rename -n не означает то же, что и -n в mv -n. Запуск rename -n не перемещает файлы вообще. Запуск mv -n перемещает файлы, если для этого не потребуется переписывать существующий файл в пункте назначения, что означает, что mv -n дает вам безопасность, которую вы автоматически получаете с помощью rename (если вы не запустите rename -f ). Это применимо только в ситуациях, когда у вас есть все файлы в диапазоне. :

for i in {0001..0012}; do mv -n "ome$i.tif" "$(printf 'ome%04dc%d.tif' "$(((10#$i - 1) / 2 + 1))" "$((2 - 10#$i % 2))")"; done

Вот как работает эта петля Bash:

for i in {0001..0012} выполняет команды после do двенадцать раз, при этом i принимает другое значение каждый раз. У этого цикла только одна такая команда перед done, что означает конец тела цикла. (Концептуально, когда элемент управления попадает на done, он переходит к следующей итерации цикла, а i - как следующее значение.) Эта одна команда:

mv -n "ome$i.tif" "$(printf 'ome%04dc%d.tif' "$(((10#$i - 1) / 2 + 1))" "$((2 - 10#$i % 2))")" $i появляется несколько раз в цикле. Это расширение параметра, и оно заменяется текущим значением i. ome$i.tif расширяется до одного из ome0001.tif, ome0002.tif, ome0003.tif и т. д., в зависимости от того, какое значение имеет значение i. Включение ведущих 0s путем записи {0001..0012} вместо {1..12} делает этот аргумент mv, который дает старое имя файла, простое для записи. $( ) - подстановка команд. Внутри я запускаю команду printf, которая выводит желаемый текст второго аргумента на mv, который дает новое имя файла. Все это заключено в цитатах " ", поэтому избегают нежелательных расширений - в частности, глобирования и разбиения слов. При подстановке команд $(...) заменяется выходом, созданным при запуске команды ....

Команда, которая выводит имя файла назначения, такова:

printf 'ome%04dc%d.tif' "$(((10#$i - 1) / 2 + 1))" "$((2 - 10#$i % 2))" $i появляется несколько раз в цикле. Это расширение параметра, и оно заменяется текущим значением i. Для выполнения вычислений каждый из двух аргументов использует расширение параметра . Весь $((...)) заменяется результатом вычисления выражения .... ome$i.tif расширяется до одного из ome0001.tif, ome0002.tif, ome0003.tif и т. д., в зависимости от того, какое значение имеет значение i. Включение начальных 0s путем записи {0001..0012} вместо {1..12} делает этот аргумент mv, который дает старое имя файла, простое для записи. Арифметика здесь такая же, как я использовал из rename, за исключением того, что деление в Bash автоматически является целым делением - оно автоматически обрезает дробную часть, поэтому нет необходимости использовать что-либо, соответствующее функции int Perl.

1 Ошибка выделения синтаксиса, используемого для кода Bash на этом сайте, в настоящее время вызывает все, после того, как # будет недоступен. Некорректный # обычно запускает комментарий в Bash, хотя в этом случае это не так. Вам не нужно беспокоиться об этом - ваш интерпретатор Bash не будет делать ту же ошибку.

1 Ошибка подсветки синтаксиса, используемая для кода Bash на этом сайте в настоящее время вызывает все после того, как # будет недоступен. Некорректный # обычно запускает комментарий в Bash, хотя в этом случае это не так. Вам не нужно беспокоиться об этом - ваш интерпретатор Bash не допустит ошибку.

5
ответ дан 18 July 2018 в 06:05

Вы можете написать цикл оболочки для этого, если вы действительно этого хотите.

Если вы хотите, чтобы команда, которая работает в системах, которые не имеют rename или чья rename команда не prename, или вы хотите, чтобы его несколько легче поняли люди, которые знают Bash, но не Perl, или по какой-либо другой причине вы хотите реализовать это как цикл в своей оболочке, который вызывает команду mv, вы можете. (В противном случае я рекомендую метод rename в моем другом ответе на это.)

Ubuntu имеет Bash 4, в котором mv сохраняет начальные нули, поэтому {0001..0012} расширяется до 0001 0002 0003 0004 0005 0006 0007 0008 0009 0010 0011 0012. Это подходит только в ситуациях, когда у вас есть все файлы в диапазоне. Основываясь на описании проблемы в вашем вопросе, похоже, это так. В противном случае он все равно будет работать, но вы получите целую кучу сообщений об ошибках для разрывов, что затруднит обнаружение каких-либо других ошибок, которые могут быть действительно важны. Замените 0012 вашей фактической верхней границей.

Поскольку перед mv появляется echo, эта команда просто печатает команды mv, которые будут выполняться, без фактического запуска: 1

for i in {0001..0012}; do echo mv -n "ome$i.tif" "$(printf 'ome%04dc%d.tif' "$(((10#$i - 1) / 2 + 1))" "$((2 - 10#$i % 2))")"; done

Это использует ту же основную идею, что и в echo , как по мере прохождения арифметики, так и по значению %04d и %d в строках формата , Это можно сделать с помощью {1..12}, но тогда это было бы еще более сложным, потому что для замены двух $( ) команд вместо printf потребовалось бы printf.

Пожалуйста, держите что -n в rename -n не означает то же, что и -n в mv -n. Запуск rename -n не перемещает файлы вообще. Запуск mv -n перемещает файлы, если для этого не потребуется переписывать существующий файл в пункте назначения, что означает, что mv -n дает вам безопасность, которую вы автоматически получаете с помощью rename (если вы не запустите rename -f ). Это применимо только в ситуациях, когда у вас есть все файлы в диапазоне. :

for i in {0001..0012}; do mv -n "ome$i.tif" "$(printf 'ome%04dc%d.tif' "$(((10#$i - 1) / 2 + 1))" "$((2 - 10#$i % 2))")"; done

Вот как работает эта петля Bash:

for i in {0001..0012} выполняет команды после do двенадцать раз, при этом i принимает другое значение каждый раз. У этого цикла только одна такая команда перед done, что означает конец тела цикла. (Концептуально, когда элемент управления попадает на done, он переходит к следующей итерации цикла, а i - как следующее значение.) Эта одна команда:

mv -n "ome$i.tif" "$(printf 'ome%04dc%d.tif' "$(((10#$i - 1) / 2 + 1))" "$((2 - 10#$i % 2))")" $i появляется несколько раз в цикле. Это расширение параметра, и оно заменяется текущим значением i. ome$i.tif расширяется до одного из ome0001.tif, ome0002.tif, ome0003.tif и т. д., в зависимости от того, какое значение имеет значение i. Включение ведущих 0s путем записи {0001..0012} вместо {1..12} делает этот аргумент mv, который дает старое имя файла, простое для записи. $( ) - подстановка команд. Внутри я запускаю команду printf, которая выводит желаемый текст второго аргумента на mv, который дает новое имя файла. Все это заключено в цитатах " ", поэтому избегают нежелательных расширений - в частности, глобирования и разбиения слов. При подстановке команд $(...) заменяется выходом, созданным при запуске команды ....

Команда, которая выводит имя файла назначения, такова:

printf 'ome%04dc%d.tif' "$(((10#$i - 1) / 2 + 1))" "$((2 - 10#$i % 2))" $i появляется несколько раз в цикле. Это расширение параметра, и оно заменяется текущим значением i. Для выполнения вычислений каждый из двух аргументов использует расширение параметра . Весь $((...)) заменяется результатом вычисления выражения .... ome$i.tif расширяется до одного из ome0001.tif, ome0002.tif, ome0003.tif и т. д., в зависимости от того, какое значение имеет значение i. Включение начальных 0s путем записи {0001..0012} вместо {1..12} делает этот аргумент mv, который дает старое имя файла, простое для записи. Арифметика здесь такая же, как я использовал из rename, за исключением того, что деление в Bash автоматически является целым делением - оно автоматически обрезает дробную часть, поэтому нет необходимости использовать что-либо, соответствующее функции int Perl.

1 Ошибка выделения синтаксиса, используемого для кода Bash на этом сайте, в настоящее время вызывает все, после того, как # будет недоступен. Некорректный # обычно запускает комментарий в Bash, хотя в этом случае это не так. Вам не нужно беспокоиться об этом - ваш интерпретатор Bash не будет делать ту же ошибку.

1 Ошибка подсветки синтаксиса, используемая для кода Bash на этом сайте в настоящее время вызывает все после того, как # будет недоступен. Некорректный # обычно запускает комментарий в Bash, хотя в этом случае это не так. Вам не нужно беспокоиться об этом - ваш интерпретатор Bash не допустит ошибку.

5
ответ дан 24 July 2018 в 18:30

Другие вопросы по тегам:

Похожие вопросы: