Isto irá capitalizar a primeira letra de cada palavra, exceto a extensão final:
rename -n 's/\b(.+?)\b/\u$1/g; s/(.+)\.(.)/$1\.\l$2/' *
Eu testei com esses arquivos:
$ ls -1
'a file with a '$'\n''new line.foo'
'a file with spaces.txt'
justonelongfilename.ext
no-extensions-here
this.has.many.extensions.pdf
E ele será renomeado como:
$ rename -n 's/\b(.+?)\b/\u$1/g; s/(.+)\.(.)/$1\.\l$2/' *
a file with a
new line.foo -> A File With A
New Line.foo
a file with spaces.txt -> A File With Spaces.txt
justonelongfilename.ext -> Justonelongfilename.ext
no-extensions-here -> No-Extensions-Here
this.has.many.extensions.pdf -> This.Has.Many.Extensions.pdf
O truque é primeiro capitalizar cada primeira letra, ignorando as extensões, e depois voltar e fazer a extensão em minúsculas:
-
s/\b(.+?)\b/\u$1/g; : O .+? é um padrão não-ganancioso, o que significa que encontrará a correspondência mais curta possível. Como ele está ancorado por limites de palavras ( \b ), isso localizará todas as palavras (todas por causa do% finalg). Estes são então substituídos pela versão capitalizada (primeira letra maiúscula) deles mesmos ( \l$1 ).
-
s/(.+)\.(.)/$1\.\l$2/ : o .+ é ganancioso, por isso encontrará a correspondência mais longa possível. Isso significa a string mais longa até um% final . , após o qual será a extensão (se houver). Substituímos a correspondência por tudo antes da extensão ( $1 ), um . e a extensão com a primeira letra inferior novamente ( \l$2 ).
A recursão é bastante fácil também. Se o seu shell é bash (se você não sabe, provavelmente é), você pode usar a opção globstar que faz com que ** corresponda a 0 ou mais subdiretórios:
shopt -s globstar
Agora, execute o comando rename assim (isso também funcionará em qualquer arquivo do diretório atual):
rename -n 's/\b(.+?)\b/\u$1/g; s/(.*)\.(.)/$1\.\l$2/' **
Para limitá-lo apenas a arquivos ou diretórios com extensões, use **/*.* em vez de ** .
Como alternativa, use find :
find /path/to/dir -exec rename -n 's/\b(.+?)\b/\u$1/g; s/(.*)\.(.)/$1\.\l$2/' {} +
E, para limitar a esses arquivos e diretórios com uma extensão:
find /path/to/dir -name '*.*' -exec rename -n 's/\b(.+?)\b/\u$1/g; s/(.*)\.(.)/$1\.\l$2/' {} +
Note que todas essas soluções renomearão alegremente os diretórios, bem como os arquivos . Se você não quiser isso, tenha cuidado com o local para reciclar ou forneça um padrão mais específico, como *.txt .
Em todos os exemplos, remova o -n para fazê-los realmente fazer alguma coisa. O -n faz com que rename simplesmente imprima o que ele faria e não realmente faça qualquer coisa. Útil para testes.