Primeiro, alguns assuntos sobre shell:
- Não use
for fname in 'find …' , pois isso irá manchar nomes de arquivos e falhará (porque a linha de comando é muito longa) se houver muitos arquivos com nomes muito longos. Use find -exec em vez disso. Como você precisa de expansão de shell no comando executado por find , invoca um shell .
- Você precisa de aspas duplas em torno das substituições de comandos, bem como das substituições de variáveis (
"$fname" , "$(echo …)" ).
-
echo maneja barras invertidas em alguns shells (ele também manipula alguns argumentos que começam com - , mas isso não é um problema aqui, pois todos os argumentos começarão com ./ ). Uma maneira de imprimir qualquer string é literalmente printf "%s\n" "$fname" ou printf "%s" "$ fname" para evitar uma nova linha final. Aqui não vejo razão para pegar o hash do nome do arquivo mais uma nova linha final em oposição ao hash do nome do arquivo.
Então, recebemos este comando:
find . -type f -exec sh -c 'mv "$0" "$(printf "%s" "$0" | sha1sum | cut -f1 -d" ").html' {} \;
Será um pouco mais rápido invocar um shell para um lote inteiro de nomes de uma só vez.
find . -type f -exec sh -c 'for fname; do mv "$fname" "$(printf "%s" "$fname" | sha1sum | cut -f1 -d" ").html; done' _ {} +
Um problema com esse método é que, se mv começar a agir antes que find tenha terminado de percorrer o diretório, os arquivos que foram movidos poderão ser selecionados por mv . Isso não é um problema com seu comando porque ele aguarda que find termine antes de começar a mover os arquivos. Portanto, coloque os arquivos renomeados em uma hierarquia de diretórios diferente. Isso resolverá outro problema que seu comando proposto também possui, que é que mv pode sobrescrever um arquivo existente que por acaso é chamado <sha1sum>.html .
mkdir ../staging
find . -type f -exec sh -c 'for fname; do mv "$fname" ../staging/"$(printf "%s" "$fname" | sha1sum | cut -f1 -d" ").html; done' _ {} +
find . -depth \! -name "." -type d -exec rmdir {} +
mv ../staging/* .
Agora, vá para sua pergunta principal: dois arquivos com caminhos diferentes serão mapeados para dois hashes SHA-1 diferentes. Matematicamente falando, existem strings distintas com hashes SHA-1 idênticos (isso é óbvio, já que existem infinitas cadeias de caracteres, mas apenas finamente muitos hashes). No entanto, praticamente ninguém sabe como encontrá-los: não há colisão conhecida para o SHA-1. É possível que um dia no futuro o SHA-1 seja quebrado, caso em que seu procedimento estará seguro apenas contra colisões acidentais, não contra invasores mal-intencionados. Se isso acontecer (não em breve), você deve atualizar para o que for considerado um algoritmo hash seguro no momento.
Quanto à sua segunda pergunta: o hash é totalmente determinado pela string hash. Portanto, se você tiver dois arquivos chamados tweedledum/staple e tweedledee/staple e executar esse procedimento de renomeação a partir de cada diretório tweedledee e tweedledum , os dois diretórios acabarão com um arquivo chamado 1c0ee9c1eed005a476403c7651b739ae5bc7cf2a.html . Se você deseja ter nomes diferentes, é necessário colocar algum conteúdo diferenciado no texto com hash, como o nome do diretório.