переименовать все файлы в каталоге в md5-хэш их имени файла (не содержимого)

Должен ли быть Linux, или другие unix-файлы можно?

Полная система NetBSD может быть собрана из исходных текстов, используя их сборку Система .sh . Система, на которой вы строите, даже не обязательно должна быть NetBSD, я сделал это из Linux или OS X. Сборка может производить установку .iso, так что вам не нужно возиться с загрузчиками, чтобы получить новую ОС. Бег.

После сборки и установки базовой системы вы можете легко установить другие пакеты из исходного кода с помощью диспетчера пакетов NetBSD pkgsrc .

9
14.09.2017, 10:11
3 ответа

Me gusta esa respuesta de una línea, pero se rompe porque analiza el nombre del archivo. También lo mejoré un poco con hash sha.

find -iname "*.jpg" -exec sha1sum '{}' ';' | while read sum file ; do mv -v "$file" "`dirname '$file'`/$sum".jpg ; done

Creo que también saca los archivos y los pone en la base de donde se ingresó el comando.

Gracias.

0
27.01.2020, 20:04

Этот подход мне часто нравится использовать.

ls | sed "s|^\(.*\)\.\([^\.]*\)$|mv \1.\2 \\`echo \1 \| md5sum \| cut -d' ' -f 1\\`.\2|" | sh -

Команда "ls" создает поток текстовых строк. Команда "sed" преобразует каждую строку с помощью правил соответствия шаблону -. Команда «sed» выводит команду «mv», которая затем передается через оболочку «sh» для выполнения. Параметры команды «mv» аналогичны «mv oldfilename newfilename», которая переименовывает файл. Я создаю новое имя файла -с помощью команды sed, которая берет часть перед последней точкой и повторяет ее на входе команды «md5sum», а затем берет только хэш из ее вывода.

Проходя через мой процесс, сначала перечислите файлы ('head -n 3', чтобы увидеть только первые 3 строки):

ls | head -n 3
    1000-26092016.xml
    1000-27092016.xml
    12312-28092016.xml

Затем подумайте о преобразовании с помощью sed (без передачи каких-либо сгенерированных команд через оболочку)

ls | sed "s|^\(.*\)\.\([^\.]*\)$|mv \1.\2 \1.\2|" | head -n 3
    mv 1000-26092016.xml 1000-26092016.xml
    mv 1000-27092016.xml 1000-27092016.xml
    mv 12312-28092016.xml 12312-28092016.xml

Существует три шаблона соответствия:

^\(.*\)      = match from start-of-line up to a dot
\.           = matches a single dot
\([^\.]*\)$  = match 0-or-more non-dot chars from end of line

Я хочу использовать sed для замены входного имени файла на "mv filename NEWfilename", но поскольку я передаю команды через оболочку, я могу генерировать команды, которые получают md5sum, например

echo "1000-26092016" | md5sum
    55b18a6b0add4a318b0079e18512b4e8  -

чтобы получить только хэш

echo "1000-26092016" | md5sum | cut -d' ' -f 1
    55b18a6b0add4a318b0079e18512b4e8

В оболочке unix мы можем использовать операторы обратной кавычки (`некоторую _команду `)для запуска подкоманды -, например

echo "howdy date there"
    howdy date there
echo "howdy `date` there"
    howdy Fri Sep 15 18:39:00 IST 2017 there

Вернемся к команде mv.Я хочу, чтобы sed производил «mv здесь и там» с заменой «там» командой «обратная кавычка», чтобы получить md5sum. Строка внутри строки sed replace -начинается так

ls | sed "s|^\(.*\)\.\([^\.]*\)$|mv \1.\2 `echo \1 | md5sum | cut -d' ' -f 1`.\2|" | head -n 3
    mv 1000-26092016.xml     b026324c6904b2a9cb4b88d6d61c81d1.xml
    mv 1000-27092016.xml     b026324c6904b2a9cb4b88d6d61c81d1.xml
    mv 12312-28092016.xml    b026324c6904b2a9cb4b88d6d61c81d1.xml

Но явно создается один и тот же хэш для каждого имени файла, так как команда -с обратной галочкой запускается до того, как sed увидит строку. Чтобы остановить запуск команды backtick в оболочке, чтобы sed выводил обратные кавычки, мы должны добавить косую черту (также к символу канала -), поэтому снова:

ls | sed "s|^\(.*\)\.\([^\.]*\)$|mv \1.\2 \`echo \1 \| md5sum \| cut -d' ' -f 1\`.\2|" | head -n 3
    mv 1000-26092016.xml     `echo 1000-26092016 | md5sum | cut -d' ' -f 1`.xml
    mv 1000-27092016.xml     `echo 1000-27092016 | md5sum | cut -d' ' -f 1`.xml
    mv 12312-28092016.xml    `echo 12312-28092016 | md5sum | cut -d' ' -f 1`.xml

Выходные данные также требуют, чтобы имена файлов были заключены в кавычки в случае пробелов, поэтому

ls | sed "s|^\(.*\)\.\([^\.]*\)$|mv \"\1.\2\" \"\`echo \1 \| md5sum \| cut -d' ' -f 1\`.\2\"|" | grep trick
    mv "a trick€€ fíle nÁme.xml" "`echo a trick€€ fíle nÁme | md5sum | cut -d' ' -f 1`.xml"

Итак, давайте попробуем это, пропустив его через оболочку:

ls | sed "s|^\(.*\)\.\([^\.]*\)$|mv \"\1.\2\" \"\`echo \1 \| md5sum \| cut -d' ' -f 1\`.\2\"|" | grep trick | sh -

Сработало? я думаю:

echo "a trick€€ fíle nÁme" | md5sum
    629db9c3071928ba0746f18444713b65  -
ls 629db9c3071928ba0746f18444713b65*
    629db9c3071928ba0746f18444713b65.xml

Вот способ перекрестной -проверки; используйте опцию «ls» «-i» для вывода узла файловой системы unix i -(, который не изменяется с помощью «mv»):

ls -1i | sort -n >.before
ls | sed "s|^\(.*\)\.\([^\.]*\)$|mv \"\1.\2\" \"\`echo \1 \| md5sum \| cut -d' ' -f 1\`.\2\"|" | sh -
ls -1i | sort -n >.after
cut -d' ' -f 1.before | while read I ; do echo "mv'd \"`grep ${I}.before`\" to \"`grep ${I}.after`\"" | sed "s| *$I *||g" ; done | head -n 3
    mv'd "1000-26092016.xml" to "55b18a6b0add4a318b0079e18512b4e8.xml"
    mv'd "1000-27092016.xml" to "b1baa80d99d5edf85c8aeb98185dd440.xml"
    mv'd "12312-28092016.xml" to "2b2d692bd047b64c99f7b9161349d430.xml"

Или с помощью команды «вставить» (пакет «coreutils»)

paste.before.after | head -n 3
    36703389 1000-26092016.xml  36703389 55b18a6b0add4a318b0079e18512b4e8.xml
    36703390 1000-27092016.xml  36703390 b1baa80d99d5edf85c8aeb98185dd440.xml
    36703391 12312-28092016.xml 36703391 2b2d692bd047b64c99f7b9161349d430.xml
2
27.01.2020, 20:04

Для подхода AWK:

find [Directory] -type f [various other find options] | 
     awk '{orig=$0; 
           match($0,/^.*\//,path); sub("^"path[0], "");
           match($0, /.[[^.]+$/,ext); sub(ext[0]"$", "");
           ("echo \"" $0 "\"|md5sum") | getline;
           com=sprintf("mv \"%s\" \"%s%s%s\"", orig, p[0], $1, ext[0]);
           print(com)
           }'

Современные findкоманды не требуют каталога для ввода ., поэтому [Каталог] можно оставить пустым. -type fнаходит только файлы, что удобно, так как md5sumне любит каталоги, и изменение имени каталога во время работы не было бы хорошей идеей. Используйте -iname pattern, если вы хотите использовать только некоторые файлы, например. -iname \*.dat, если важен регистр, используйте -nameвместо -iname.

Части match(...); sub(...)извлекают части имени файла и заменяют их во входной строке. Обратите внимание, что "^"и "$"добавляются [pre/ap], чтобы предотвратить замену строки, которая может повторять путь/расширение.

Замените print(com)на system(com), чтобы выполнить переименование.

Если вы хотите использовать md5sumфактического файла в качестве имени, вы можете использовать тот факт, что md5sumвыводит сумму и входное имя файла, чтобы сделать что-то вроде:

 find -type f -exec md5sum '{}' ';' | 
     while read sum file ; do 
       [echo] mv "$file" "`dirname $file`/$sum".extension ; 
     done

while read sum fileпримет 2 аргумента, результаты команды md5sum, и назначит с ними переменные sumи file. Поскольку в sumне должно быть пробелов, readдолжно работать нормально.

Очевидно, что [echo]следует удалить при фактическом запуске, но всегда полезно проверить поиск перед запуском при тестировании любых изменений в сценарии.

Все это предполагает, что вы используете bash. Кроме того, это можно напечатать как одну длинную строку:

find -iname \*.jpg -exec md5sum '{}' ';' | while read sum file ; do mv "$file" "`dirname $file`/$sum".jpg ; done
1
27.01.2020, 20:04

Теги

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