У меня есть каталог, содержащий подкаталоги, содержащие много файлов, названных как:
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...
И это во всех подкаталогах главного каталога.
Но я не могу узнать, как сделать это.
Это возможно? Как?
Редактировать на основе комментария:
Если вы хотите переключить счетчик, т. Е. <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
.
Благодаря 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 для его справки и терпения...
С 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