Script de shell para corrigir nomes de arquivos incorretos?

1

Estou na minha pequena empresa; e, apesar dos meus terríveis avisos, todos colocam arquivos no servidor com nomes horríveis, incluindo os principais & espaços à direita, caracteres ruins (incluindo \ ; / + . < > - etc!)

Eles fazem isso acessando o servidor (FreeBSD / FreeNAS) via AFP em Macs, então nenhuma parte do sistema reclama.

Existe um script que eu possa usar para percorrer uma árvore de diretórios inteira e corrigir nomes de arquivos incorretos?

Basicamente, substitua todos os espaços & ASCII ruim com _ ... e se um arquivo já existe, apenas coloque um _2 ou algo assim no final.

Eu não suponho que haja uma maneira de fazer com que o sistema faça valer boas convenções de nomes de arquivos, está?

Obrigado!

    
por Ze'ev 20.08.2012 / 03:50

1 resposta

3

Eu usaria bash e encontraria. Tenho certeza de que há uma opção mais simples, mas eis o que eu criei:

  1. Isso pode lidar com nomes de arquivos que contenham "/" (a localização dará um aviso, ignore-a), mas funcionará somente em arquivos no diretório atual (sem subdiretórios). Eu não conseguia descobrir como dizer bash ou encontrar para diferenciar entre um "/" em um nome de arquivo e um "/" que faz parte do caminho.

    for i in $(find . -maxdepth 1 -type f  -name "*[\:\;><\@\$\#\&\(\)\?\\/\%]*" | sed 's/\.\///'); do mv "$i" ${i//[\;><\@\$\#\&\(\)\?\\/\%]/_}; done
    
  2. Este não pode lidar com nomes de arquivos contendo "/", mas funcionará em todos os arquivos no diretório atual e em seus subdiretórios :

    for i in $(find . -type f  -name "*[\:\;\>\<\@\$\#\&\(\)\?\\%]*"); do mv "$i" ${i//[\;><\@\$\#\&\(\)\?\\%]/_}; done
    

Certifique-se de testar estes antes de executar . Eles funcionaram bem nos poucos testes que eu fiz, mas eu não estava exaustivo. Também tenha em mente que estou em um sistema linux. A implementação específica do find, e talvez do bash, pode diferir da sua.

EDIT: Alterar o comando mv $i para 'mv -i $ i' fará com que o mv avise antes de sobrescrever um arquivo existente.

EDIT2: Para lidar com nomes de arquivos com espaços, você pode alterar a variável bash IFS (Input Field Separator) assim (adaptada de aqui ):

SAVEIFS=$IFS; IFS=$(echo -en "\n\b"); for i in $(find . -type f  -name "*[\:\;\>\<\@\$\#\&\(\)\?\\%\ ]*"); do mv "$i" ${i//[\;><\@\$\#\&\(\)\?\\%\ ]/_}; done; IFS=$SAVEIFS

Eu também modifiquei a expressão regular para corresponder / substituir espaços com sublinhados. O bit SAVEIFS apenas retorna a variável IFS para sua configuração original.

EXPLICAÇÃO:

for i in $(command); do something $i; done

Este é um loop bash genérico. Ele passará pela saída de um comando, configurando sequencialmente a variável $ i para cada um dos valores retornados pelo comando e fará algo com ela.


find . -maxdepth 1 -type f  -name "*[\:\;><\@\$\#\&\(\)\?\\/\%]*" '

Encontre todos os arquivos no diretório atual cujo nome contenha um dos seguintes caracteres: :;><@$#&()\/% . Para adicionar mais, apenas escape com "\" (por exemplo, "\") e adicione-os à lista entre colchetes ([]). Provavelmente, nem todos esses caracteres precisam ser escapados, mas eu nunca consigo lembrar quais são variáveis especiais em qual ambiente, então eu escapei de tudo, apenas no caso.

sed 's/\.\///

Remova o diretório atual da saída do find, imprima "foo" em vez de "./foo".

mv "$i" ${i//[\;><\@\$\#\&\(\)\?\\/\%]/_}

Toda vez que esse pequeno scipt fizer um loop, $ i será o nome de um arquivo mal-nomeado. Este comando irá mover (renomear) aquele arquivo mudando todos os caracteres indesejados para "_". Procure por substituição de bash para mais informações.

por 20.08.2012 / 05:17