Um problema com renomeação recursiva é que qualquer que seja o método usado para localizar os arquivos, ele passa todo o caminho para rename
, não apenas o nome do arquivo. Isso dificulta a criação de renomeações complexas em pastas aninhadas.
Eu uso a ação find
-execdir
para resolver esse problema. Se você usar -execdir
em vez de -exec
, o comando especificado será executado a partir do subdiretório que contém o arquivo correspondente. Portanto, em vez de passar todo o caminho para rename
, ele passa apenas ./filename
. Isso torna muito mais fácil escrever o regex.
find /the/path -type f \
-name '*.abc' \
-execdir rename 's/\.\/(.+)\.abc$/version1_.abc/' '{}' \;
Em detalhes:
-
-type f
significa procurar apenas arquivos, não diretórios
-
-name '*.abc'
significa significa apenas corresponder nomes de arquivos que terminam em .abc
- As barras invertidas após
-type
e -name
são o caractere de continuação da linha de bash. Eu os uso para tornar este exemplo mais legível, mas eles não são necessários na prática.
- No entanto, a barra invertida no final da linha
-execdir
é necessária. Ele está lá para expor o ponto-e-vírgula, que finaliza o comando executado por -execdir
. Diversão!
Explicação do regex:
-
s/
início da regex
-
\.\/
corresponde ao líder ./que o -execdir passa. Use \ para escapar do. e / metacaracteres
-
(.+)
corresponde ao nome do arquivo. Os parênteses capturam a correspondência para uso posterior
-
\.abc
escape do ponto, combine o abc
-
$
ancora a correspondência no final da string
-
/
marca o final da parte "correspondência" da expressão regular e o início da parte "substituir"
-
version1_
adicione este texto a todos os nomes de arquivo
-
faz referência ao nome do arquivo existente, porque capturamos com parênteses. Se você usar vários conjuntos de parênteses na parte "match", você pode consultá-los aqui usando $ 2, $ 3, etc.
-
.abc
o novo nome do arquivo terminará em .abc. Não há necessidade de escapar do metacaractere ponto aqui na seção "substituir"
-
/
end do regex
Antes
tree --charset=ascii
|-- a_file.abc
|-- Another.abc
|-- Not_this.def
'-- dir1
'-- nested_file.abc
Depois
tree --charset=ascii
|-- version1_a_file.abc
|-- version1_Another.abc
|-- Not_this.def
'-- dir1
'-- version1_nested_file.abc
Dica: a opção rename
's -n é útil. Ele faz uma corrida a seco e mostra a você quais nomes ele mudará, mas não faz alterações.