Esta é uma abordagem para renomear arquivos com nomes aleatórios, sugerida por Terdon. A vantagem desta abordagem é que ela resolve automaticamente as colisões de nomes de arquivos:
randomname() { base64 < /dev/urandom | tr -dC a-z0-9 | head -c4; }
for f in *.png; do
newName=$(randomname).png
while [ -e "$newName" ]; do
newName=$(randomname).png
done
mv -- "$f" "$newName"
done
E aqui está outra abordagem, usando zmv
. A vantagem é que você pode usá-lo para renomear arquivos em lote com extensões diferentes:
zmv '*(.*)' '${(Lr:8:)$(uuidgen)}$1'
Quero modificar a segunda abordagem para que ela resolva automaticamente as colisões de nomes de arquivos como a primeira, mas não entendo como. Alguém poderia ajudar com isso?
Se você só precisa lidar com múltiplas extensões, isso pode ser feito com uma variação do loop na primeira abordagem. Isso usa o
:e
modificador de expansão para adicionar a extensão do arquivo original ao novo nome (e algunszsh
-ismos para evitar a repetição do código do novo nome):Com
newName::=
, o resultado das próximas expansões (auuidgen
chamada e o ramal) será atribuído ànewName
variável. É{}
simplesmente um corpo de loop vazio, já que tudo o que precisávamos estava na[[ ]]
condição.Usando uma abordagem semelhante com
zmv
:Isso demonstra o
-n
flag, que é um dos motivos de usozmv
- ele imprimirá o que ocorreria sem fazer nada, o que é muito útil para depuração. Remova o-n
para realmente renomear os arquivos. Uma advertência: isso irá automaticamente para o próximo nome se houver uma colisão com um arquivo que já esteja no sistema de arquivos. Mas no caso muito improvável deuuidgen
gerar dois nomes idênticos durante umazmv
chamada,zmv
detectará a colisão potencial e sairá sem renomear nenhum arquivo.Puramente para entretenimento, aqui está uma versão que evita quase todas as dependências externas e usa um codificador base64 escrito inteiramente em
zsh
. É baseado em alguns experimentos que fiz há algum tempo:A probabilidade de colisões é baixa. Portanto, espere que não haja colisões e tente novamente, se houver. Você pode detectar colisões porque o zmv possui uma mensagem de erro específica para isso.
O limite para o número de tentativas é tanto no caso de haver um erro e a renomeação ter uma grande chance de colisões, quanto no caso de ocorrer algum outro erro, mas a string
both map to
aparecer em um nome de arquivo.Aqui estão algumas outras abordagens que são mais complexas do que o necessário para o problema em questão, mas demonstram o uso do zmv fora de sua zona de conforto. A interface zmv foi projetada principalmente para situações em que o método para calcular a substituição de cada nome de arquivo é independente dos outros nomes de arquivo. No entanto, existem alguns truques para ter dependências entre nomes substitutos.
Uma coisa fácil é injetar um contador no substituto. Você pode incrementar o contador em uma expressão aritmética. Isso sobrevive de um nome de arquivo para outro porque a expressão de substituição não é avaliada em um subshell.
Executar código arbitrário na expressão de substituição é fácil: é apenas uma substituição de comando. Mas isso coloca o código em um subshell, para que você não possa manter um estado arbitrário entre as chamadas. No entanto, para esta tarefa específica, tudo que você precisa é da variável interna
from
que o zmv mantém para controlar os novos nomes de arquivos. Presumo que os nomes dos arquivos não terminem com uma nova linha.A
from
variável não está documentada, embora exista desde quezmv
foi introduzida. E se não quiséssemos confiar nisso? Depois fica mais complicado, mas ainda podemos atualizar o estado através de${VAR::=VALUE}
substituições de parâmetros. O código abaixo é usadon
como uma variável temporária para o novo nome eseen[$n]
rastreia os novos nomes de arquivos que já estão alocados.${…:+}
oculta o resultado de uma expansão de parâmetro aninhado.Uma abordagem menos intuitiva que leva a um código mais simples é preparar o texto de substituição assim que você fizer a correspondência de padrões. Dentro do padrão, você pode usar o
e
qualificador glob para executar código arbitrário.