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

У меня есть несколько файлов с неправильными именами:

$ ls
devoirNote1_1_2.R  devoirNote1_1_5.R  devoirNote1_4_1.R
devoirNote1_1_3.R  devoirNote1_1.R    devoirNote1.R
devoirNote1_1_4.R  devoirNote1_2_1.R  example140.R

Я хочу заменить все DevOirNote1_i_j.R целыми числами i и j, кроме DevOirNote1_4_1.R в DevOirNote1_ {i + 1} _j.R (без изменений оставлен только DevOirNote1_4_1.R ).

Я подумал об использовании команды mv , например mv DevOirNote1 _ * _ 2.R DevOirNote1_2_2.R , но когда несколько файлов совпадают (например, если оба DevOirNote1_1_2.R и DevOirNote1_3_2.R ), это создает проблему.

Следовательно, как создать сценарий или командную строку, которая переименовывает мои файлы, увеличивая одну из переменных в именах файлов, но не все из них?

0
26.03.2017, 00:28
3 ответа

Для этого можно использовать утилиту Perl rename(*). Она применяет заданную команду Perl к каждому заданному имени файла и переименовывает файл в то, на что команда изменила имя.

Таким образом, это изменит _1_ на _2_ для всех файлов, которым соответствует glob.

rename 's/_1_/_2_/' devoirNote1_*_2.R

Численное увеличение можно сделать с помощью /e, модифицировав команду замены, сделав часть замены фрагментом Perl вместо литерала.

rename -v 's/_(\d+)_/"_" . ($1 + 1) . "_"/e' devoirNote1_*_2.R

Это позволит выбрать часть имени файла с цифрами между символами подчеркивания, захватить цифры до $1 и заменить их числом, увеличенным на единицу, с добавлением символов подчеркивания. -v для режима verbose. Со списком файлов в вашем примере это выведет devoirNote1_1_2.R переименован в devoirNote1_2_2.R, как и ожидалось.

Затронутыми файлами будут все файлы, которым соответствует glob в конце командной строки.

Хотя обратите внимание, что если у вас есть, скажем, 1_1_2 и 1_2_2, переименование первого из них будет неудачным, поскольку оно столкнется со следующим. Для этого нужно либо дать имена файлов в обратном порядке, либо сначала изменить их на не коллидирующую форму, а затем обратно, например, добавив дополнительный символ.

(* не инструмент переименования util-linux. См. здесь и здесь)

0
28.01.2020, 04:47

Скрипт будет излишним для двух (пакетных) ходов. Используйте утилиту mmv :

mmv devoirNote1_2_"*" devoirNote1_3_#1
mmv devoirNote1_1_"*" devoirNote1_2_#1

Конечно, в таком порядке. Если ходов намного больше, чем два, то сценарий действительно будет предпочтительнее.

0
28.01.2020, 04:47

Здесь мы используем отрицательный просмотр , чтобы отфильтровать файлы * Note1_3_2.R и * Note1_4_2.R из списка поиска.

OP хотел оставить * Note1_4_2.R нетронутым => мы также не можем коснуться одного предыдущего файла, а именно * Note1_3_2.R , поскольку мы некуда это мв.

Логика цикла for предназначена для выполнения обратной числовой сортировки по порядковому номеру между 1 и 2, чтобы мы могли выполнить неразрушающую операцию mv.

perl -e '
   /(.*)_(\d+)_(.*)/ and
      rename $_, join "_", $1, $2+1, $3 or warn "Could not mv the file <<$_>>\n"
      for
         map  {                  $_->[0]                   }
         sort { $b->[2] <=> $a->[2] || $b->[1] <=> $a->[1] }
         map  {             [$_, /_(\d+)_(\d+)/]           }
         grep {     /^devoirNote1_(?![34]_1.R)\d+_\d+.R/   }
         <*.R>
'
0
28.01.2020, 04:47

Теги

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