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
20151209
ist natürlich das Datum
12434
und 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/date
Verzeichnis.
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 find
und 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 danninstall
um jede Datei in das entsprechende Verzeichnis zu kopieren userID/date
(das liegt daran, dass ich faul bin) - ohne install
die 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 .WAV
Dateien 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, zsh
ist es einfacher und kürzer mit zmv
(auch weil zsh
es 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
, $2
usw.
Hier führt zmv
with -p
die Funktion dtcp
anstelle 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 -n
steht fürProbelauf; entfernen Sie es, um den Befehl tatsächlich auszuführen.