-
A maneira fácil de obter o script do slhck para pesquisar subpastas e arquivos recursivamente, se você estiver usando o bash, é adicionar
shopt -s globstar
e, em seguida, alterar*
para**
. Isso não funcionará corretamente se você tiver diretórios com caracteres “ilegais” em seus nomes. Você pode contornar isso simplesmente executando o script n +1 vezes onde n é o número máximo de diretórios com caracteres ilegais em qualquer caminho. Por exemplo, se você tiver um diretóriof@cat
, e um diretóriodog#
abaixo disso, e um diretóriofox!
abaixo disso, você precisaria executar o script quatro vezes.Eu dou uma maneira melhor de fazer isso, abaixo.
O script do - slhck deveria dizer
mv -i
em vez demv
. Se você tivesse arquivos com nomes, digamos,cost+tax
ecost-tax
, o script irá renomeá-los paracosttax
(oucost_tax
, depois de fazermos essa mudança). Isso irá destruir o primeiro arquivo com o segundo arquivo. A opção-i
( i nteractive) fará com quemv
solicite confirmação. Você terá que lidar com essas colisões manualmente. - Para substituir caracteres "ilegais" por sublinhados,
altere
${file//[^0-9A-Za-z.]}
para${file//[^0-9A-Za-z.]/_}
(ou, melhor ainda,${file//[^0-9A-Za-z._]/_}
).
Assim, com as alterações acima, o script do slhck se torna
shopt -s globstar
for f in "$1"/**
do
dir="$(dirname "$f")"
file="$(basename "$f")"
mv -i -- "$f" "${dir}/${file//[^0-9A-Za-z._]/_}"
done
Ao executar isso,
não se esqueça de fornecer um argumento (por exemplo, .
);
caso contrário, ele tentará renomear todos os arquivos no sistema de arquivos
(começando em /
).
Você provavelmente deveria colocar algo no script
para verificar se o argumento $1
não é nulo.
Isso tem problemas com diretórios com caracteres ilegais em seus nomes
porque o **
se expande para uma lista de todos os arquivos e diretórios
na subárvore sob $1
com ramificações na ordem de cima para baixo.
Então, se você tem f@cat/dog#
,
ele verá f@cat
e f@cat/dog#
como argumentos.
Então, ele renomeará f@cat
para f_cat
e, em seguida, procurará f@cat/dog#
- que não existe mais, porque foi renomeado para f_cat/dog#
.
Podemos consertar isso fazendo
find "$1" -depth -name '*[^0-9A-Za-z._]*' -exec sh -c \
'for f do dir="$(dirname "$f")"; file="$(basename "$f")";
mv -i -- "$f" "${dir}/${file//[^0-9A-Za-z.]/_}"; done' sh {} +
A opção -depth
para find
informa
para examinar as ramificações de diretório na ordem de baixo para cima.
A diretiva -name
faz com que ela veja apenas nomes de arquivos
que precisam para serem renomeados.
(O outro script dará mensagens de erro
quando ele tenta renomear arquivos para si
porque seus nomes não têm nenhum caractere ilegal.)
find
, em seguida, passa os nomes para um shell
que faz a mesma coisa que o script, mas como um único comando.