Na verdade, for i in *; do something; done
trata cada nome de arquivo corretamente, exceto que os nomes de arquivos que começam com .
são excluídos da correspondência de curinga. Para fazer a correspondência de todos os arquivos (exceto .
e ..
) de forma portável, combine * .[!.]* ..?*
e pule qualquer arquivo inexistente resultante de um padrão não correspondente sendo deixado intacto.
Se você teve problemas, provavelmente é porque você não citou $i
corretamente depois. Sempre coloque aspas duplas em torno de substituições de variáveis e substituições de comandos: "$foo"
, "$(cmd)"
, a menos que você pretenda que a divisão de campos e globbing ocorram.
Se você precisar passar o nome do arquivo para um comando externo (você não o faz aqui), tome cuidado para que echo "$foo"
nem sempre imprima $foo
literalmente. Alguns shells executam expansão de barra invertida, e alguns valores de $foo
começando com -
serão tratados como uma opção. A maneira segura e compatível com POSIX de imprimir uma string exatamente é
printf '%s' "$foo"
ou printf '%s\n' "$foo"
para adicionar uma nova linha no final. Outra coisa a observar é que a substituição de comandos remove as novas linhas finais; Se você precisar manter novas linhas, um possível truque é acrescentar um caractere não-nova linha aos dados, certifique-se de que a transformação retenha esse caractere e, finalmente, trunque esse caractere. Por exemplo:
mangled_file_name="$(printf '%sa' "$file_name" | tr -sc '[:alnum:]-+_.' '[_*]')"
mangled_file_name="${mangled_file_name%a}"
Para extrair o md5sum do arquivo, evite ter o nome do arquivo na saída md5sum
, pois isso dificultará a remoção. Passe os dados na entrada padrão de md5sum
.
Observe que o comando md5sum
não está no POSIX. Algumas variantes unix têm md5
ou nada. cksum
é POSIX, mas sujeito a colisão.
Veja Agarrando a extensão em um nome de arquivo sobre como obter a extensão do arquivo.
Vamos colocar tudo junto (não testado). Tudo aqui funciona em qualquer shell POSIX; você pode ganhar um pouco, mas não muito, com os recursos do bash.
for old_name in * .[!.]* ..?*; do
if ! [ -e "$old_name" ]; then continue; fi
hash=$(md5sum <"$old_name")
case "$old_name" in
*.*.gz|*.*.bz2) # double extension
ext=".${old_name##*.}"
tmp="${old_name%.*}"
ext=".${old_name##*.}$ext";;
?*.*) ext=".${old_name##*.}";; # simple extension
*) ext=;; # no extension
esac
mv -- "$old_name" "$hash$ext"
done
Observe que não considerei o caso em que já existe um arquivo de destino pelo nome especificado. Em particular, se você tiver arquivos cujo nome se pareça com sua convenção adotada, mas onde a parte da soma de verificação não corresponde ao conteúdo do arquivo e em vez disso a de outro arquivo com a mesma extensão, o que acontecerá dependerá da ordem lexicográfica relativa os nomes dos arquivos.