Kopieren Sie eine große Anzahl von Dateien in eine datumsstrukturierte Verzeichnisreihenfolge

Kopieren Sie eine große Anzahl von Dateien in eine datumsstrukturierte Verzeichnisreihenfolge

Ich muss ungefähr 40.0000 Dateien in datumsstrukturierte Ordner kopieren.
Beispieldatei:

/var/public/voicelogging/quality_monitoring/20151209/bbbbbb_I_20151209-185841_xxxxxx_12434_89343.WAV

Ist eine der vielen Dateien, die ich kopieren muss/home/username/logging/

Der Dateiname enthält zwei Variablen, die ich verwenden muss:

bbbbbb_I_20151209-185841_xxxxxx_12434_89343.WAV

20151209ist natürlich das Datum
12434und die ID des Benutzers, der die Datei erstellt hat.

Was ich brauche, ist ein Skript/ein Einzeiler, der in einem Verzeichnis nach der Benutzer-ID suchen kann.

Erstellen Sie dann ein Verzeichnis mit der Benutzer-ID in /home/username/logging. Nachdem der Ordner erstellt wurde, muss für jedes Datum, das es finden kann, ein Verzeichnis erstellt werden.
Und platzieren Sie jede Datei im richtigen userid/dateVerzeichnis.
Beispiel für ein Ergebnisverzeichnis.

/home/username/logging/12434/20151209/bbbbbb_I_20151209-185841_xxxxxx_12434_89343.WAV

Ich habe einen Einzeiler zum Erstellen der Datumsverzeichnisse erstellt, muss das Benutzer-ID-Verzeichnis aber noch selbst erstellen.

find /var/public/voicelogging/quality_monitoring/ -type f -name "*12434*" | sed -r 's/^.{65}//' | cut -c1-8 | xargs -I {} mkdir {} /home/username/logging/12434

Wie kann ich die richtige Datei an den richtigen Ort kopieren?

Antwort1

Einweg mit findund install:

find /var/public/voicelogging/quality_monitoring -name \*.WAV -exec sh -c '
bn=${0##*/}; x=${bn%%-*}; dt=${x##*_}; y=${bn%_*}; id=${y##*_} 
install -D "$0" "/home/username/logging/${id}/${dt}/${bn}"' {} \;

Dies verwendet die Parametererweiterung, um das Datum ${dt}und die Benutzer-ID ${id}aus dem Dateinamen zu extrahieren und verwendet danninstallum jede Datei in das entsprechende Verzeichnis zu kopieren userID/date(das liegt daran, dass ich faul bin) - ohne installdie letzte Zeile durch Folgendes zu ersetzen:

dest=/home/username/logging/${id}/${dt}; mkdir -p "${dest}" && cp "$0" "${dest}"' {} \;

Wenn Sie lieber eine Schleife über diese „Datums“-Verzeichnisse und dann eine Schleife über die .WAVDateien in jedem Verzeichnis bevorzugen:

for d in /var/public/voicelogging/quality_monitoring/*; do
  dt=${d##*/}
  for f in $d/*.WAV; do
    bn=${f##*/}; y=${bn%_*}; id=${y##*_}
    dest=/home/username/logging/${id}/${dt}
    mkdir -p "${dest}" && cp "${f}" "${dest}"
  done
done

Wenn Sie es haben, zshist es einfacher und kürzer mit zmv(auch weil zshes intelligenter ist und Sie Variablenerweiterungen verschachteln können, z. B. ${${file%_*}##*_}würde es ausreichen, die Benutzer-ID zu extrahieren):

dtcp () {                                                                     
mkdir -p $3 && cp $1 $2 $3
}
autoload zmv
zmv -n -p dtcp '/var/public/voicelogging/quality_monitoring/(*)/(*).WAV' \
'/home/username/logging/${${2%_*}##*_}/$1'

Die (*)s erstellen Rückverweise, die im zweiten Parameter als verwendet werden können $1, $2usw.
Hier führt zmvwith -pdie Funktion dtcpanstelle von aus mv. Die Funktion erstellt das Verzeichnis und kopiert dann die Datei in das neu erstellte Verzeichnis. Die Argumente (nicht zu verwechseln mit den Rückverweisen oben) sind:
$1: --
was das Ende der Optionen bedeutet
$2: /var/public/voicelogging/quality_monitoring/(*)/(*).WAV'
das ist die Datei, die kopiert werden muss und
$3: /home/username/logging/${${2%_*}##*_}/$1
das ist das Ziel
Beachten Sie, dass -nsteht fürProbelauf; entfernen Sie es, um den Befehl tatsächlich auszuführen.

verwandte Informationen