Переименование файлов путем добавления “циклически повторяющий” суффикс

У меня есть каталог, содержащий подкаталоги, содержащие много файлов, названных как:

file1.tif
file2.tif
file3.tif
file4.tif
file5.tif
file6.tif
file7.tif...

Я хочу добавить "циклически повторяющийся" суффикс c1, c2 и c3, получить имена файлов:

file1c1.tif
file2c2.tif
file3c3.tif
file4c1.tif
file5c2.tif
file6c3.tif
file7c1.tif...

И это во всех подкаталогах главного каталога.

Но я не могу узнать, как сделать это.

Это возможно? Как?

5
задан 30 August 2016 в 03:36

3 ответа

Редактировать на основе комментария:

Если вы хотите переключить счетчик, т. Е. <number> в c<number>, циклически переключаться между 1 и 3:

Dry- run:

shopt -s globstar
for d in **/*/; do 
    ( cd "$d" && pwd && count=1 && shopt -s nullglob && for f in file*.tif; do 
        echo mv -i "$f" "${f%.tif}"c${count}.tif
        if ((count=3)); then 
            count=1
        else
            ((count++))
        fi
     done ) 
done

Действие:

shopt -s globstar
for d in **/*/; do 
    ( cd "$d" && count=1 && shopt -s nullglob && for f in file*.tif; do 
        mv -i "$f" "${f%.tif}"c${count}.tif
        if ((count=3)); then 
            count=1
        else
            ((count++))
        fi
     done ) 
done

Пример:

$ tree
.
├── bar
│   ├── file1.tif
│   ├── file2.tif
│   ├── file3.tif
│   └── file4.tif
├── foo
│   ├── egg
│   │   ├── file1.tif
│   │   └── file2.tif
│   ├── file1.tif
│   ├── file2.tif
│   └── file3.tif
└── spam
    ├── file1.tif
    └── file2.tif

$ shopt -s globstar
$ for d in **/*/; do ( cd "$d" && pwd && count=1 && shopt -s nullglob && for f in file*.tif; do \
    echo mv -i "$f" "${f%.tif}"c${count}.tif; if ((count=3)); then count=1; else ((count++)); fi; done ); done
/home/foobar/bar
mv -i file1.tif file1c1.tif
mv -i file2.tif file2c2.tif
mv -i file3.tif file3c3.tif
mv -i file4.tif file4c1.tif
/home/foobar/foo
mv -i file1.tif file1c1.tif
mv -i file2.tif file2c2.tif
mv -i file3.tif file3c3.tif
/home/foobar/foo/egg
mv -i file1.tif file1c1.tif
mv -i file2.tif file2c2.tif
/home/foobar/spam
mv -i file1.tif file1c1.tif
mv -i file2.tif file2c2.tif

$ for d in **/*/; do ( cd "$d" && count=1 && shopt -s nullglob && for f in file*.tif; do \
    mv -i "$f" "${f%.tif}"c${count}.tif; if ((count=3)); then count=1; else ((count++)); fi; done ); done

$ tree
.
├── bar
│   ├── file1c1.tif
│   ├── file2c2.tif
│   ├── file3c3.tif
│   └── file4c1.tif
├── foo
│   ├── egg
│   │   ├── file1c1.tif
│   │   └── file2c2.tif
│   ├── file1c1.tif
│   ├── file2c2.tif
│   └── file3c3.tif
└── spam
    ├── file1c1.tif
    └── file2c2.tif

Оригинальный ответ :

С помощью bash:

shopt -s globstar
for d in **/*/; do ( cd "$d" && pwd && count=1 && shopt -s nullglob \
    && for f in file*.tif; do echo mv -i "$f" "${f%.tif}"c${count}.tif; \
        ((count++)); done ); done
  • Здесь мы перебираем имена каталогов, опция оболочки globstar позволяет рекурсивно обходить каталог

  • Часть внутри () работает в подоболочке, это предотвращает изменение cd в текущей оболочке

  • Мы cd -бывают в каталогах, находят файлы file*.tif и переименовывают их по мере необходимости

  • , сохраняя счетчик приращений, count, для каждого файла при переименовании


Выше приведен пробный запуск, и он покажет вам каталог, в котором будет выполнено переименование и какая команда mv будет выполнена. Если вы удовлетворены, сделайте:

shopt -s globstar
for d in **/*/; do ( cd "$d" && count=1 && shopt -s nullglob && \
  for f in file*.tif; do mv -i "$f" "${f%.tif}"c${count}.tif; ((count++)); done ); done

Существует предостережение о том, что в качестве оболочки выполняется лексическая сортировка, например, файлов. file10.tif будет переименован ранее, чем file2.tif. Если вы не хотите этого, выполните некоторую сортировку перед переименованием или используйте zsh с опцией numericglobsort.

6
ответ дан 23 November 2019 в 08:45

Благодаря heemayl во всем разобрались. Мы должны были изменить обозначенный инкрементный циклом цикл немного, так как он не работал в наших руках. Мы изменились: если ((count=3)) в: если ((" $count" == 3)) заключительный код, который мы теперь успешно используем:

    shopt -s globstar
for d in **/*/; do 
    ( cd "$d" && count=1 && shopt -s nullglob && for f in *.tif; do 
       echo mv -i "$f" "${f%.tif}"c${count}.tif

if (("$count"==3)); then 
count=1
        else 
((count++))
        fi
     done ) 
done

Еще раз спасибо к heemayl для его справки и терпения...

0
ответ дан 23 November 2019 в 08:45

С find + жемчуг базирующимся prename (иначе rename на некотором более раннем Ubuntus), Вы могли соответствовать последовательности цифр перед литералом . и затем запишите это в нужном формате с помощью подразделения по модулю, например.

find . -name '*.tif' -execdir prename -vn -- 's/(\d+)\./sprintf "%dc%d.", $1, ($1-1)%3+1/e' {} +

( -vn флаги позволяют Вам делать 'пробный прогон', чтобы видеть, как файлы были бы переименованы прежде, чем фиксировать).


Напр. данный

$ tree
.
├── bar
│  ├── file1.tif
│  ├── file2.tif
│  ├── file3.tif
│  ├── file4.tif
│  ├── file5.tif
│  ├── file6.tif
│  └── file7.tif
├── foo
│  ├── egg
│  │  ├── file1.tif
│  │  └── file2.tif
│  ├── file1.tif
│  ├── file2.tif
│  └── file3.tif
└── spam
    ├── file1.tif
    └── file2.tif

4 directories, 14 files

Затем

find . -name '*.tif' -execdir prename -- 's/(\d+)\./sprintf "%dc%d.", $1, ($1-1)%3+1/e' {} +

результаты в

$ tree
.
├── bar
│  ├── file1c1.tif
│  ├── file2c2.tif
│  ├── file3c3.tif
│  ├── file4c1.tif
│  ├── file5c2.tif
│  ├── file6c3.tif
│  └── file7c1.tif
├── foo
│  ├── egg
│  │  ├── file1c1.tif
│  │  └── file2c2.tif
│  ├── file1c1.tif
│  ├── file2c2.tif
│  └── file3c3.tif
└── spam
    ├── file1c1.tif
    └── file2c2.tif

4 directories, 14 files
7
ответ дан 23 November 2019 в 08:45

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

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