if-Bedingung zwischen Zeilen innerhalb verschiedener Listen, Listen nach Übereinstimmungen analysieren, dann cp verwenden

if-Bedingung zwischen Zeilen innerhalb verschiedener Listen, Listen nach Übereinstimmungen analysieren, dann cp verwenden

Kann mir bitte jemand einen Vorschlag machen, wie das geht?

Ich habe zwei Listen (beide mit SHA1-Summen und ihren relativen Dateinamen), die aber unterschiedlich formatiert sind. Hier ist ein Beispiel:
list01.txt

artist'ssomesong.mp3,3f1dfd39e88e00477483dfd578d5284f5490a0a5
hello(previous one).sh,55a5fdde4843fc2f9d9e691cb658b6389d698b22
mymovie [1989, director's cut].mov,4bdee0fc0eb7a3dbc5bbe2b65a02a1f9dc76c443
[etc...]

list02.txt

3f1dfd39e88e00477483dfd578d5284f5490a0a5  /path/to/my new music/album.wav
f77921adf6748f65fe688a5484ed901d4g9932hh  /path/to/movies/[YEAR]/mymovie [1989, director's cut].mov
55a5fdde4843fc2f9d9e691cb658b6389d698b22  /path/to/scripts,regexs/hello(previous one).sh
[etc...]


Wie Sie sehen, ist der einzige gültige Eintrag für sha1sum 55a5fdde4843fc2f9d9e691cb658b6389d698b22mit Dateinamen hello(previous one).sh(2. Zeile in list01.txtund 3. Zeile in list02.txt).
Dateinamen und Pfade können Leerzeichen und Sonderzeichen enthalten (z. B.: ' " [ ] ( ) { } usw.).
Das Einzige, worüber Sie 100 % sicher sein können, ist, dass es immer als ; list01.txtformatiert ist und immer (zwei Leerzeichen vor /) hat. ,sha1sumlist02.txtsha1sum /

Wie im Titel dieser Frage möchte ich einif-Bedingungin einem Bash-Skript, das beide Listen auf Übereinstimmungen überprüft (TRUE ist, wennsowohl sha1sum als auch filename sind gleich) und wenn es sie findet, dann kopiert es jedes Vorkommen mit

cp $source $destination
source=reads the /path/to/filename from list02.txt
destination=/wherever/i/want/


Danke!

Antwort1

Annahmen:

  • GNU-Tools sind vorhanden (nicht standardmäßige xargsOptionen cp, möglicherweise nicht funktionierender NUL-Trennzeichen in anderen awk)
  • Die Länge des Hashes beträgt immer 40 Zeichen
  • Es gibt immer zwei Leerzeichen zwischen Hash und Dateipfad inlist02.txt
  • In beiden Dateien sind keine Pipe |-Zeichen vorhanden (sonst anderes Trennzeichen verwenden)

Erster Schritt, beide Dateien zusammenführen:

join -t'|' -1 2 \
    <(sed -E 's/,(.{40})$/|\1/' list01.txt | sort -t'|' -k2) \
    <(sed -E 's/(.{40})  /\1|/' list02.txt | sort -t'|' -k1)
  • Erste Datei: Trennzeichen ,durch ersetzen |und Datei nach dem zweiten Feld sortieren
  • Zweite Datei: Trennzeichen (zwei Leerzeichen) durch ersetzen |und nach dem ersten Feld sortieren
  • Verbinde die Dateien im Hash-Feld

Ausgabe:

3f1dfd39e88e00477483dfd578d5284f5490a0a5|artist'ssomesong.mp3|/path/to/my new music/album.wav
55a5fdde4843fc2f9d9e691cb658b6389d698b22|hello(previous one).sh|/path/to/scripts,regexs/hello(previous one).sh

Verwenden Sie dann, awkum zu testen, ob der Dateiname von Feld2 als Dateiname im letzten Feld vorhanden ist. Wenn dies zutrifft, drucken Sie das letzte Feld mit einem NUL-Trennzeichen und leiten Sie das Ergebnis weiter, um xargsdie Dateien in das Zielverzeichnis zu kopieren.

join -t'|' -1 2 \
    <(sed -E 's/,(.{40})$/|\1/' list01.txt | sort -t'|' -k2) \
    <(sed -E 's/(.{40})  /\1|/' list02.txt | sort -t'|' -k1) \
| awk -F '|' '
  {
    fname1=$2; sub(/.*\//, "", fname1) # extract filename1
    fname2=$3; sub(/.*\//, "", fname2) # extract filename2
  }
  fname1 == fname2{ printf $3 "\0" }   # compare filenames, print filepath with NUL separator
' | xargs -r0 cp -n -t /path/to/destination

Kopieroptionen:

  • -nvorhandene Dateien nicht überschreiben
  • -tZielverzeichnis

Als Skript:

#!/bin/bash

join -t'|' -1 2 \
    <(sed -E 's/,(.{40})$/|\1/' "$1" | sort -t'|' -k2) \
    <(sed -E 's/(.{40})  /\1|/' "$2" | sort -t'|' -k1) \
| awk -F '|' '
  {
    fname1=$2; sub(/.*\//, "", fname1) # extract filename1
    fname2=$3; sub(/.*\//, "", fname2) # extract filename2
  }
  fname1 == fname2{ printf $3 "\0" }   # compare filenames, print filepath with NUL separator
' | xargs -r0 cp -n -t "$3"

Führen Sie es wie folgt aus:

./script.sh list1 list2 /path/to/destination

verwandte Informationen