2016-04-28 11 views
7

Ich habe ein Verzeichnis mit einer Struktur wie folgt:md5 alle Dateien in einem Verzeichnisbaum

. 
├── Test.txt 
├── Test1 
│   ├── Test1.txt 
│   ├── Test1_copy.txt 
│   └── Test1a 
│    ├── Test1a.txt 
│    └── Test1a_copy.txt 
└── Test2 
    ├── Test2.txt 
    ├── Test2_copy.txt 
    └── Test2a 
     ├── Test2a.txt 
     └── Test2a_copy.txt 

Ich mag würde einen Bash-Skript erstellen, die in diesem Verzeichnis eine MD5-Prüfsumme jede Datei macht. Ich möchte in der Lage sein, den Skriptnamen in der CLI einzugeben und dann den Pfad zu dem Verzeichnis, das ich hashen möchte und es funktionieren zu lassen. Ich bin mir sicher, dass es viele Möglichkeiten gibt, dies zu erreichen. Zur Zeit habe ich:

#!/bin/bash 

for file in "$1" ; do 
    md5 >> "${1}__checksums.md5" 
done 

Das hängt einfach und es funktioniert nicht. Vielleicht sollte ich Find verwenden?

Ein Vorbehalt - die Verzeichnisse, die ich hashen möchte, werden Dateien mit verschiedenen Erweiterungen haben und nicht immer genau diese Baumstruktur haben. Ich will etwas, das auch in diesen verschiedenen Situationen funktionieren wird.

Antwort

3

Wie wäre:

find /path/you/need -type f -exec md5sum {} \; > checksums.md5

Update # 1: den Befehl Verbesserte basierend auf @ twalberg Empfehlung weißen Leerzeichen in Dateinamen zu handhaben.

Update # 2: Verbesserte basierend auf @ jil Vorschlag, unnötigen xargs Aufruf zu entfernen und stattdessen -exec Möglichkeit finden verwenden.

Update # 3: @Blake eine naive Implementierung des Skripts würde wie folgt aussehen:

#!/bin/bash 
# Usage: checksumchecker.sh <path> 
find "$1" -type f -exec md5sum {} \; > "$1"__checksums.md5 
+0

Ich würde 'find/path -type f -print0 | empfehlen xargs -0 md5sum', um mit Dateinamen umzugehen, die sonst ungewollt durch Whitespace geteilt werden könnten ... – twalberg

+0

@twalberg Guter Punkt, danke! Ich aktualisiere die Antwort. – taskalman

+0

Danke @taskalman. "Sie können den Pfad erstellen und den Dateinamen aus $ 1 ausgeben, wenn wir ihn in Ihr Skript einfügen. Beachten Sie, dass Sie die Schrägstriche in Ihrem path-Parameter behandeln müssen, damit er Teil des Dateinamens in Ihrem Skript wird." Kannst du das etwas weiter erklären? Ich verstehe nicht ganz, was du meinst. – Bleakley

1
#!/bin/bash 
shopt -s globstar 
md5sum "$1"/** > "${1}__checksums.md5" 

Erläuterung: shopt -s globstar(manual) ermöglicht ** rekursive glob Wildcard. Dies bedeutet, dass "$1"/** in eine Liste aller rekursiven Dateien unter dem als Parameter $1 angegebenen Verzeichnis erweitert wird. Dann ruft das Skript einfach md5sum mit dieser Dateiliste als Parameter auf und > "${1}__checksums.md5" leitet die Ausgabe in die Datei um.

+1

Ihre Antwort kann richtig sein, aber es wäre viel hilfreicher, wenn Sie könnte erklären, was es macht oder wie es funktioniert – kommradHomer

+1

@jil ja, kannst du bitte erklären, wie das funktioniert? Ich denke, es könnte sein, wonach ich suche. – Bleakley

+0

@Blake Beachten Sie, dass versteckte Dateien nicht hashed werden. Wenn Sie möchten, dass versteckte Dateien nicht ignoriert werden, aktivieren Sie die Option 'dotglob':' shopt -s dotglob' [[source] (https://www.gnu.org/software/bash/manual/html_node/The-Shopt- Builtin.html # The-Shop-Builtin)]. – TeWu

16

Mit md5deep

md5deep -r path/to/dir > sums.md5 

Mit find und md5sum

find relative/path/to/dir -type f -exec md5sum {} + > sums.md5 

bewusst sein, dass, wenn Sie mit md5sum -c sums.md5 auf Ihren MD5-Summen laufen zu überprüfen, müssen Sie es aus dem gleichen Verzeichnis ausgeführt werden, von denen Sie haben sums.md5 Datei generiert. Dies liegt daran, dass find Pfade ausgibt, die sich auf Ihren aktuellen Standort beziehen, die dann in die Datei sums.md5 eingegeben werden.

Wenn dies ein Problem ist, können Sie relative/path/to/dir absolut machen (z. B. indem Sie $PWD/ vor Ihren Pfad setzen). Auf diese Weise können Sie von jedem beliebigen Ort aus auf sums.md5 überprüfen. Nachteil ist, dass jetzt sums.md5 absolute Pfade enthält, was es größer macht.

Voll ausgestattete Funktion find und md5sum

Sie diese Funktion, um Ihre .bashrc Datei setzen können (in Ihrem $HOME Verzeichnis):

function md5sums { 
    if [ "$#" -lt 1 ]; then 
    echo -e "At least one parameter is expected\n" \ 
      "Usage: md5sums [OPTIONS] dir" 
    else 
    local OUTPUT="checksums.md5" 
    local CHECK=false 
    local MD5SUM_OPTIONS="" 

    while [[ $# > 1 ]]; do 
     local key="$1" 
     case $key in 
     -c|--check) 
      CHECK=true 
      ;; 
     -o|--output) 
      OUTPUT=$2 
      shift 
      ;; 
     *) 
      MD5SUM_OPTIONS="$MD5SUM_OPTIONS $1" 
      ;; 
     esac 
     shift 
    done 
    local DIR=$1 

    if [ -d "$DIR" ]; then # if $DIR directory exists 
     cd $DIR # change to $DIR directory 
     if [ "$CHECK" = true ]; then # if -c or --check option specified 
     md5sum --check $MD5SUM_OPTIONS $OUTPUT # check MD5 sums in $OUTPUT file 
     else       # else 
     find . -type f ! -name "$OUTPUT" -exec md5sum $MD5SUM_OPTIONS {} + > $OUTPUT # Calculate MD5 sums for files in current directory and subdirectories excluding $OUTPUT file and save result in $OUTPUT file 
     fi 
     cd - > /dev/null # change to previous directory 
    else 
     cd $DIR # if $DIR doesn't exists, change to it to generate localized error message 
    fi 
    fi 
} 

Nachdem Sie source ~/.bashrc laufen, Sie md5sums wie normale verwenden können Befehl:

md5sums path/to/dir 

erzeugt checksums.md5 Datei in path/to/dir Verzeichnis, enthält MD5 Summen aller Dateien in diesem Verzeichnis und Unterverzeichnisse. Verwendung:

md5sums -c path/to/dir 

Summen aus path/to/dir/checksums.md5 Datei zu überprüfen.

Beachten Sie, dass path/to/dir relativ oder absolut sein kann, md5sums funktioniert in beide Richtungen. Die resultierende checksums.md5 Datei enthält immer Pfade relativ zu path/to/dir. Sie können einen anderen Dateinamen als den Standard checksums.md5 verwenden, indem Sie -o oder --output als Option angeben. Alle Optionen, außer -c, --check, -o und --output werden an md5sum übergeben.

Erste Hälfte von md5sums Funktionsdefinition ist für die Analyseoptionen verantwortlich. Weitere Informationen dazu finden Sie unter this answer. Die zweite Hälfte enthält erläuternde Kommentare.

+0

** Hinweis: ** Nach meiner Erfahrung führt die Verwendung von '-exec command {} +' Variante von 'exec' dazu, dass es schneller ausgeführt wird als bei Variante '-exec Befehl;' wird verwendet. – TeWu

+0

Vielen Dank! Ich schätze es sehr, dass dieses komplexe (für mich!) Skript auskommentiert wurde. – Bleakley

+0

@TeWu 'md5deep' funktioniert nicht in' Ubuntu 16.04' –

1

aktualisiert Antwort

Wenn Sie die Antwort unten mögen, oder eine der anderen, können Sie eine Funktion machen, der den Befehl für Sie tut. Also, um es zu testen, geben Sie Folgendes in das Terminal eine Funktion zu deklarieren:

function sumthem(){ find "$1" -type f -print0 | parallel -0 -X md5 > checksums.md5; } 

Dann können Sie einfach verwenden:

sumthem /Users/somebody/somewhere 

Wenn das funktioniert, wie Sie möchten, können Sie diese Zeile addieren, Ende Ihres „bash-Profil“ und die Funktion wird erklärt und verfügbar sein, wenn Sie angemeldet sind. Ihr „bash-Profil“ ist wahrscheinlich in $HOME/.profile

Ursprüngliche Antwort

Warum nicht alle Ihre CPU-Kerne parallel für Sie arbeiten lassen?

find . -type f -print0 | parallel -0 -X md5sum 

Dies findet alle Dateien (-type f) im aktuellen Verzeichnis (.) und druckt sie mit einem Null-Byte am Ende. Diese werden dann in GNU Parallel übergeben, die besagt, dass die Dateinamen mit einem Nullbyte enden (-0) und dass es so viele Dateien wie möglich gleichzeitig machen soll (-X) um das Erstellen eines neuen Prozesses für jede Datei zu speichern und es sollte md5sum die Dateien.

Dieser Ansatz zahlt den größten Bonus, in Bezug auf die Geschwindigkeit, mit großen Bildern wie Photoshop-Dateien.

+0

Ja, das würde funktionieren, aber ich müsste den gesamten Befehl ständig neu eingeben. Ich möchte ein Skript, bei dem das zu hashende Verzeichnis eine Variable ist und der Name der Dateiausgabe auf dieser Variablen basiert. Ich möchte nicht jedes Mal einen Suchbefehl eingeben müssen - nur einen Skriptnamen, sagen wir "makechecksum", und wirf das zu hashende Verzeichnis in die CLI. – Bleakley

+0

Danke! sehr hilfreich. – Bleakley

1
md5deep -r $your_directory | awk {'print $1'} | sort | md5sum | awk {'print $1'} 
+1

Bitte bearbeiten Sie Ihre Antwort mit einigen Erklärungen. Code-only-Antworten machen wenig aus, um zukünftige SO-Leser zu schulen. Ihre Antwort befindet sich in der Moderationswarteschlange, weil sie von geringer Qualität ist. – mickmackusa

+0

@ AlexJurado-Bitendian hast du die Antwort überprüft, 'md5deep' funktioniert nicht in' ubuntu 16.04' –

+0

Ich nehme an, Kasun bezieht sich auf https://github.com/jessek/hashdeep/issues/365 –