
У меня есть каталог, содержащий подкаталоги, содержащие множество файлов, названных следующим образом:
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...
И это во всех подкаталогах верхнего каталога.
Но я не могу понять, как это сделать.
Возможно ли это? Как?
решение1
С помощью find
+ на основе Perl prename
(также известного как rename
некоторые ранние версии Ubuntu) вы можете сопоставить последовательность цифр перед литералом .
, а затем записать ее в желаемом формате, используя деление по модулю, например
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
решение2
Редактировать на основе комментария:
Если вы хотите циклически переключать счетчик, например, <number>
от c<number>
1 до 3:
Пробный прогон:
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
Есть оговорка, что поскольку shell выполняет лексическую сортировку, то файлы, например, file10.tif
будут переименованы раньше, чем file2.tif
. Если вы этого не хотите, выполните сортировку перед переименованием или используйте опцию zsh
with numericglobsort
.
решение3
Спасибо heemayl, все получилось. Нам пришлось немного изменить указанный цикл инкремента цикла, так как он не работал у нас. Мы изменили: if ((count=3)) на: if (("$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 за его/ее помощь и терпение...