si la condición entre líneas dentro de diferentes listas, analiza las listas en busca de coincidencias, luego usa cp

si la condición entre líneas dentro de diferentes listas, analiza las listas en busca de coincidencias, luego usa cp

Por favor, ¿alguien podría sugerirme cómo hacerlo?

Tengo dos listas (ambas con sha1sums y sus nombres de archivo relativos) pero con un formato diferente, aquí hay un ejemplo:
lista01.txt

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

lista02.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...]


Como puede ver, la única entrada buena es sha1sum 55a5fdde4843fc2f9d9e691cb658b6389d698b22con nombre de archivo hello(previous one).sh(segunda línea list01.txty tercera línea list02.txt).
Los nombres de archivo y las rutas pueden contener espacios en blanco y caracteres especiales (por ejemplo: ' " [ ] ( ) { } y así sucesivamente...).
Lo único de lo que podemos estar 100% seguros es que list01.txtsiempre tendrá el formato ,sha1sum; y list02.txtsiempre tendrá sha1sum /(dos espacios antes de /).

Como en el título de esta pregunta, me gustaría utilizar uncondición-sien un script bash que verifica ambas listas para encontrar coincidencias (VERDADERO es siTanto sha1sum como filename son iguales) y cuando los encuentre, copiará cada ocurrencia usando

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


¡Gracias!

Respuesta1

Supuestos:

  • xargsHay herramientas GNU presentes (opciones y no estándar cp, posiblemente separador NUL que no funcione en otros awk)
  • La longitud del hash es siempre de 40 caracteres.
  • Siempre hay dos caracteres de espacio que separan el hash y la ruta del archivo enlist02.txt
  • No |hay caracteres de barra vertical en ambos archivos (de lo contrario, utilice un separador diferente)

Primer paso, fusionar ambos archivos:

join -t'|' -1 2 \
    <(sed -E 's/,(.{40})$/|\1/' list01.txt | sort -t'|' -k2) \
    <(sed -E 's/(.{40})  /\1|/' list02.txt | sort -t'|' -k1)
  • Primer archivo: sustituya el separador ,por |y ordene el archivo en el segundo campo
  • Segundo archivo: sustituya el separador (dos espacios) por |el primer campo y ordene
  • Unir los archivos en el campo hash

Producción:

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

Luego utilícelo awkpara probar si el nombre de archivo del campo2 está presente como nombre de archivo en el último campo. Si es verdadero, imprima el último campo con un separador NUL y canalice el resultado para xargscopiar los archivos al directorio de destino.

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

Opciones de copia:

  • -nno sobrescribir archivos existentes
  • -tdirectorio de destino

Como guión:

#!/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"

Ejecútelo como:

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

información relacionada