Linux piping find и md5sum не отправляют вывод

Пытаясь зациклить каждый файл, выполнить вырезку, извлечь первые 4 символа MD5.

Вот что я получил так далеко:

find . -name *.jpg | cut -f4 -d/ | cut -f1 -d. | md5sum | head -c 4

Проблема в том, что я не вижу больше вывода на данный момент. Как я могу отправить вывод на md5sum и продолжить отправку результата?

3 ответа

Решение

md5sum читает все от стандартного ввода до конца файла (eof) и выводит md5 сумму полного файла. Вы должны разделить ввод на строки и запустить md5sum для каждой строки, например, с помощью while read var цикл:

find . -name *.jpg | cut -f4 -d/ | cut -f1 -d. | 
  while read -r a; 
   do   echo -n $a| md5sum | head -c 4; 
  done

read встроенная команда bash прочитает одну строку из ввода в переменную оболочки $a; while цикл будет запускать тело цикла (команды между do а также done) для каждого возврата из чтения, и $a будет текущей строкой. -r опция read - не конвертировать обратную косую черту; Опция -n команды echo не добавляет новую строку (если вы хотите новую строку, удалите опцию -n из echo).

Это будет медленным для тысяч файлов и более, так как для каждого файла в цикле есть несколько forks/execs. Быстрее будут некоторые сценарии с использованием perl или python или nodejs или любого другого языка сценариев со встроенными хэш-вычислениями md5 (или с некоторой библиотекой).

Вы можете делать то, что пытаетесь сделать, с помощью короткого "вспомогательного" скрипта, из которого вы вызываете find, Например, вы можете создать короткий скрипт, чтобы найти basename каждого файла, переданного в качестве аргумента, удалите '.jpg' расширение, а затем предоставить оставшееся имя без расширения в качестве входных данных для md5sum на stdin чтобы получить md5sum самого названия. Назовите сценарий как хотите, скажем namemd5.sh, Пример:

#!/bin/bash

[ -z "$1" ] && exit 1           ## validate single argument

fname=$(basename "$1")          ## get the filename alone
fname="${fname%.jpg}"           ## remove .jpg extension

fnsum=$(md5sum - <<<"$fname")   ## get md5sum of name w/o .jpg
fnsum=${fnsum%% *}              ## remove trailing ' -'

echo "$fnsum - $fname"          ## output md5sum - name
                                ## (remove ' - $fname' for md5sum alone)

(примечание: имя предоставляется как часть выходных данных в качестве примера, удалите, если хотите md5sum один, как показано в комментарии выше)

Файлы примеров

$ find /home/david/img/wp/ -type f -name "*.jpg"
/home/david/img/wp/hacker_manifesto_1200x900.jpg
/home/david/img/wp/hacker_manifesto_by_otalicus.jpg
/home/david/img/wp/reflections-triple-1920x1200.jpg
/home/david/img/wp/hacker_wallpaper_1600x900.jpg
/home/david/img/wp/Zen.jpg
/home/david/img/wp/hacker_wallpaper_by_vanilla23-dot254.jpg
/home/david/img/wp/hacker_manifesto_1600x900.jpg

Пример использования / Вывод

$ find /home/david/img/wp/ -type f -name "*.jpg" -exec ./namemd5.sh '{}' \;
0f7d2aac158eb9f7842215e14ff6573c - hacker_manifesto_1200x900
604bc695a0bb70b8db0352267caf226f - hacker_manifesto_by_otalicus
5decea0e306f185bf988ac9934ec0e2c - reflections-triple-1920x1200
82bd8e1ad3df588eb0e0848c5f764812 - hacker_wallpaper_1600x900
0f4daba431a22c03f28977f087e4c695 - Zen
0c55cd3ebd2a847e10c20d86e80e6ceb - hacker_wallpaper_by_vanilla23-dot254
e5c1da0c2db3827d2bf81c306633cc56 - hacker_manifesto_1600x900

Вы также можете вызвать скрипт с -execdir версия внутри find а также, например

$ find /home/david/img/wp/ -type f -name "*.jpg" -execdir \
/full/path/to/namemd5.sh '{}' \;

(примечание: использование /full/path на ваш вспомогательный скрипт выше)

Как найти все файлы.jpg, затем выполнить md5sum, а затем вырезать первые 4 символа:

find . -name '*.jpg'  -exec md5sum {} \; | cut -b 1-4
Другие вопросы по тегам