2016-04-01 12 views
2

Szenario:

Mit Locky Virus auf randalieren das Rechenzentrum ich für die einzige Methode der Wiederherstellung von Dateien gefunden haben, arbeiten wird Tools wie Recuva nun das Problem mit, dass die Verwendung Es speichert alle wiederhergestellten Dateien in einem einzigen Verzeichnis. Ich würde gerne alle diese Dateien basierend auf ihren Dateierweiterungen in Kategorien verschieben. Alle JPG in einem BMP in einem anderen ... etc. Ich habe mich in Stackoverflow umgesehen und basierend auf verschiedenen anderen Fragen und Antworten konnte ich ein kleines Bash-Skript (Beispiel zur Verfügung gestellt) erstellen, das es aber immer braucht, bis es fertig ist Ich denke, ich habe die Erweiterungen durcheinander gebracht.Effeciantly in bash eine halbe Million Dateien basierend auf Erweiterung bewegen

Code:

#!/bin/bash 
path=$2 # Starting path to the directory of the junk files 
var=0  # How many records were processed 
SECONDS=0 # reset the clock so we can time the event 

clear 

echo "Searching $2 for file types and then moving all files into grouped folders." 

# Only want to move Files from first level as Directories are ok were they are 
for FILE in `find $2 -maxdepth 1 -type f` 
do 
    # Split the EXT off for the directory name using AWK 
    DIR=$(awk -F. '{print $NF}' <<<"$FILE") 
    # DEBUG ONLY 
    # echo "Moving file: $FILE into directory $DIR" 
    # Make a directory in our path then Move that file into the directory 
    mkdir -p "$DIR" 
    mv "$FILE" "$DIR" 
    ((var++)) 
done 

echo "$var Files found and orginized in:" 
echo "$(($diff/3600)) hours, $((($diff/60) % 60)) minutes and $(($diff % 60)) seconds." 

Frage:

Wie kann ich diese effiziente, während sie mit 500.000 Dateien zu tun? Der Fund braucht eine Ewigkeit, um eine Liste von Dateien zu erfassen und versucht in der Schleife ein Verzeichnis zu erstellen (selbst wenn dieser Pfad bereits vorhanden ist). Ich möchte diese beiden besonderen Aspekte der Schleife, falls möglich, effizienter behandeln.

+0

Ich denke Ihre Frage ist "Wie kann ich das schneller machen?" und die Konzentration auf das 'find' und das' mkdir' sind deine Theorien, die auf dem basieren, was du über 'mkdir' weißt und was du interaktiv gesehen hast, als das Skript ausgeführt wurde. Wenn Sie es schneller machen wollen, sollten Sie messen, wie schnell diese Teile sind, um den wahren Flaschenhals zu identifizieren. –

+1

Wenn Sie nicht wissen, dass alle zu verschiebenden Dateien nette Dateinamen ohne Leerzeichen oder Zeichen mit spezieller Bedeutung für die Shell haben, ist Ihre For-Schleife unterbrochen. – chepner

+1

Eine halbe Million "awk" -Prozesse zu fahren ist nicht ideal. Verwenden Sie die Bash-Parameterersetzung, um die Erweiterung zu erhalten. –

Antwort

2

Der Flaschenhals eines Bash-Skripts ist normalerweise die Anzahl der externen Prozesse, die Sie starten. In diesem Fall können Sie die Anzahl der Aufrufe an mv erheblich reduzieren, indem Sie erkennen, dass ein großer Prozentsatz der Dateien, die Sie verschieben möchten, ein gemeinsames Suffix wie jpg usw. hat. Beginnen Sie mit diesen.

for ext in jpg mp3; do 
    mkdir -p "$ext" 
    # For simplicity, I'll assume your mv command supports the -t option 
    find "$2" -maxdepth 1 -name "*.$ext" -exec mv -t "$ext" {} + 
done 

Verwenden -exec mv -t "$ext" {} + bedeutet find zu jedem Aufruf mv so viele Dateien wie möglich passieren. Für jede Nebenstelle bedeutet dies ein Anruf find und eine minimale Anzahl von Anrufen zu mv.

Sobald diese Dateien verschoben wurden, dann können Sie beginnen, Dateien einzeln zu analysieren.

for f in "$2"/*; do 
    ext=${f##*.} 
    # Probably more efficient to check in-shell if the directory 
    # already exists than to start a new process to make the check 
    # for you. 
    [[ -d $ext ]] || mkdir "$ext" 
    mv "$f" "$ext" 
done 

Der Kompromiss tritt bei der Entscheidung, wie viel Arbeit Sie vorher die Identifizierung der gemeinsamen Erweiterungen tun möchten die Anzahl der Iterationen der zweiten for Schleife zu minimieren.

+0

+1 für die Effizienz unter Berücksichtigung, ich brauche nicht einige Dateien Ich könnte dies anpassen, um alle DLL-Dateien zu entfernen einen Block von Dateien zu entfernen, die ich nicht brauche, bevor wir sie einzeln beschäftigen –

+0

Mit einem einzigen Verzeichnis von Dateien, die Sie gar nicht brauchen, finden Sie hier. Nur 'mv -t tgt * .glob 'wird tun (bis die Liste der Dateien zu groß wird und dann' xargs' kann nützlich sein. –

+0

Ich hielt 'find' für die Fähigkeit, dynamisch zu entscheiden, wie viele Dateien an jeden übergeben werden können Aufruf von 'mv' mit' -exec ... + '.Wenn ich mich nicht irre, ist 'xargs' darauf beschränkt, eine feste maximale Anzahl von Argumenten anzugeben, ungeachtet der kumulativen Länge der Argumente. – chepner