Переименуйте файлы со случайными символами от sha1sum. Имена будут уникальны?

# Get one character per loop, until the user presses <Enter>
while true ; do 
    read -n 1 c
    (( ${#c} == 0 )) && break # Exit the loop. Input length is 0  
                              # ie. The user has pressed Enter
    #
    if [   \( ! "$c" \< "a" -a  ! "$c" \> "z" \) \
        -o \( ! "$c" \< "A" -a  ! "$c" \> "Z" \) ]
    then
        val=($(ascii -s $c)) # build an array of ascii info for this char 
        echo " ... The decimal value of $c is: ${val[1]}"
    else
        echo -n  $'\r \r' # overwrite the invalid character
    fi 
done
2
18.05.2016, 21:59
3 ответа

sha1sum выводы будут уникальны, пока исходные данные уникальны. (Если Вы не очень чрезвычайно неудачны, и Вы нашли некоторых sha1sum коллизия).

Что касается Вашего варианта использования: это - хорошая привычка использовать printf '%s' "$fname" вместо echo "$fname", первый будет работать когда $fname -n, или -e, … Видят также enzotib комментарий, я пропустил это на первый взгляд.

Кроме того, я не уверен точно, что является Вашими мотивациями, но можно рассмотреть питание sha1sum с содержанием файла вместо имен файлов. Таким образом, Вы получили бы уникальное имя файла для каждого уникального содержания.

2
27.01.2020, 21:57
  • 1
    Обратите внимание, что использование sha1 содержания файла дало бы более уникальные результаты, но также займет намного больше времени (в зависимости от размера файлов, конечно). –  rozcietrzewiacz 19.08.2011, 15:06
  • 2
    При хешировании содержания Вы закончите с тем же именем файла, если содержание будет тем же. Это может или не может быть желательно (это не, если Вы позже хотите изменить один из файлов). –  Gilles 'SO- stop being evil' 19.08.2011, 16:19

Во-первых, несколько вопросов оболочки:

  • Не использовать for fname in `find …` поскольку это исказит имена файлов и перестанет работать (потому что командная строка является слишком длинной), если существует слишком много файлов со слишком длинными именами. Использовать find -exec вместо этого. Так как Вы должны окружить расширение в команде, выполняемой find, вызовите оболочку.
  • Вам нужны двойные кавычки вокруг замен команды, а также подстановок переменных ("$fname", "$(echo …)").
  • echo обратные косые черты искажений на нескольких оболочках (это также искажает несколько начала аргументов -, но это не проблема здесь, так как все аргументы начнутся ./). Способ распечатать любую строку буквально printf "%s\n" "$fname", или printf "%s" "$fname" для предотвращения заключительной новой строки. Здесь я не вижу оснований для взятия хеша имени файла плюс заключительная новая строка в противоположность хешу имени файла.

Таким образом, мы получаем эту команду:

find . -type f -exec sh -c 'mv "$0" "$(printf "%s" "$0" | sha1sum | cut -f1 -d" ").html' {} \;

Это будет немного быстрее для вызова оболочки для целого пакета имен сразу.

find . -type f -exec sh -c 'for fname; do mv "$fname" "$(printf "%s" "$fname" | sha1sum | cut -f1 -d" ").html; done' _ {} +

Проблема с этим методом - это если mv начинает действовать прежде find закончил пересекать каталог, файлы, которые были перемещены, могут быть взяты mv. Это не проблема с Вашей командой, потому что она ожидает find закончиться прежде, чем запустить движущиеся файлы. Так помещает переименованные файлы в другую иерархию каталогов. Это решит другую проблему, которую также имеет Ваша предложенная команда, который является этим mv может перезаписать существующий файл, который, оказывается, называют <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/* .

Теперь по Вашему основному вопросу: два файла с различными путями отобразятся на два различных хеша SHA-1. Математически разговор, там существуйте отличные строки с идентичными хешами SHA-1 (это очевидно, так как существует бесконечно много строк, но только конечно много хешей). Однако в сущности никто не знает, как найти их: нет никакой известной коллизии для SHA-1. Возможно, что однажды в будущем SHA-1 будет поврежден, в этом случае Ваша процедура будет безопасна только против случайных коллизий, не против злонамеренных взломщиков. Если это происходит (не скоро), необходимо обновить до того, что считают безопасным хеш-алгоритмом в то время.

Что касается Вашего второго вопроса: хеш полностью определяется строкой, которую Вы хешируете. Таким образом, если у Вас есть два названные файла tweedledum/staple и tweedledee/staple и Вы выполняете ту процедуру переименования из каждого каталога tweedledee и tweedledum в свою очередь затем оба каталога закончатся с названным файлом 1c0ee9c1eed005a476403c7651b739ae5bc7cf2a.html. Если Вы хотите иметь различные имена, необходимо поместить некоторое различающее содержание в хешированный текст, такой как название каталога.

2
27.01.2020, 21:57

В первую очередь, я предлагаю занять место

for fname in `find . -type f`; do

с

find . -type f | while read -r fname; do

Затем, относительно sha1sum, это должно быть "фактически" уникально, означая, что вероятность, чтобы иметь в различные файлы с той же контрольной суммой, если значительно низкий, так, чтобы можно было безопасно принять это, уникальна.

1
27.01.2020, 21:57

Теги

Похожие вопросы