
Eu tenho um diretório contendo subdiretórios contendo muitos arquivos nomeados como:
file1.tif
file2.tif
file3.tif
file4.tif
file5.tif
file6.tif
file7.tif...
Quero adicionar um sufixo "ciclismo" c1
e para obter os nomes dos arquivos c2
:c3
file1c1.tif
file2c2.tif
file3c3.tif
file4c1.tif
file5c2.tif
file6c3.tif
file7c1.tif...
E isso em todos os subdiretórios do diretório superior.
Mas não consigo descobrir como fazer isso.
Isso é possível? Como?
Responder1
Com find
+ o perl baseado prename
(também conhecido como rename
em alguns Ubuntus anteriores), você poderia combinar a sequência de dígitos antes de um literal .
e então escrevê-lo no formato desejado usando divisão de módulo, por exemplo
find . -name '*.tif' -execdir prename -vn -- 's/(\d+)\./sprintf "%dc%d.", $1, ($1-1)%3+1/e' {} +
(os -vn
sinalizadores permitem que você faça uma 'simulação' para ver como os arquivos seriam renomeados antes de enviar).
Ex. dado
$ 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
Então
find . -name '*.tif' -execdir prename -- 's/(\d+)\./sprintf "%dc%d.", $1, ($1-1)%3+1/e' {} +
resulta em
$ 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
Responder2
Editar com base no comentário:
Se você deseja alternar o contador, ou seja, <number>
alternar c<number>
entre 1 e 3:
Funcionamento a seco:
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
Ação:
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
Exemplo:
$ 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
Resposta original:
Com 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
Aqui estamos percorrendo os nomes dos diretórios,
globstar
a opção shell nos permite percorrer o diretório recursivamenteA parte interna
()
é executada em um subshell, isso evita quecd
seja modificada no shell atualEstamos
cd
entrando nos diretórios, encontrando osfile*.tif
arquivos e renomeando-os conforme necessáriomantendo um contador incremental,
count
para cada arquivo enquanto renomeia
O texto acima é uma simulação e mostrará o diretório onde a renomeação será feita e qual mv
comando será executado. Se estiver satisfeito, faça:
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
Há uma ressalva: como o shell faz a classificação lexical, os arquivos, por exemplo, file10.tif
serão renomeados antes de file2.tif
. Se você não quiser isso, faça uma classificação antes de renomear ou usar a opção zsh
with numericglobsort
.
Responder3
Graças ao heemayl, tudo foi resolvido. Tivemos que modificar um pouco o loop de incremento de ciclo indicado, pois não funcionou em nossas mãos. Mudamos: if ((count=3)) para: if (("$count"==3)) O código final que agora estamos usando com sucesso é:
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
Obrigado novamente a heemayl por sua ajuda e paciência...