если условие между строками внутри разных списков, проанализируйте списки на предмет совпадений, затем используйте cp

если условие между строками внутри разных списков, проанализируйте списки на предмет совпадений, затем используйте cp

Пожалуйста, кто-нибудь может подсказать мне, как это сделать?

У меня есть два списка (оба с sha1sums и их относительными именами файлов), но они отформатированы по-разному, вот пример:
список01.txt

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

список02.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...]


Как вы можете видеть, единственная хорошая запись — для sha1sum 55a5fdde4843fc2f9d9e691cb658b6389d698b22с именем файла hello(previous one).sh(2-я строка в list01.txtи 3-я строка в list02.txt).
Имена файлов и пути могут содержать пробелы и специальные символы (например: ' " [ ] ( ) { } и так далее...).
Единственное, в чем нужно быть на 100% уверенным, это то, что list01.txtвсегда форматируется как ,sha1sum; и list02.txtвсегда будет иметь sha1sum /(два пробела перед /).

Как и в названии этого вопроса, я хотел бы использоватьесли-условиев скрипте bash, который проверяет оба списка на предмет совпадений (TRUE — еслии sha1sum и имя файла одинаковы) и когда он их найдет, то скопирует каждое вхождение, используя

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


Спасибо!

решение1

Предположения:

  • Присутствуют инструменты GNU (нестандартные xargsи cpопциональные, возможно неработающий разделитель NUL в других awk')
  • Длина хеша всегда составляет 40 символов.
  • Всегда есть два пробела, разделяющие хэш и путь к файлу.list02.txt
  • В обоих файлах отсутствуют символы вертикальной |черты (в противном случае используйте другой разделитель)

Первый шаг — объединить оба файла:

join -t'|' -1 2 \
    <(sed -E 's/,(.{40})$/|\1/' list01.txt | sort -t'|' -k2) \
    <(sed -E 's/(.{40})  /\1|/' list02.txt | sort -t'|' -k1)
  • Первый файл: заменить разделитель ,на |и отсортировать файл по второму полю
  • Второй файл: заменить разделитель (два пробела) на |и отсортировать по первому полю
  • Объединить файлы в хэш-поле

Выход:

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

Затем используйте awkдля проверки, присутствует ли имя файла field2 как имя файла в последнем поле. Если это так, выведите последнее поле с разделителем NUL и передайте результат в конвейер для xargsкопирования файлов в целевой каталог.

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

Параметры копирования:

  • -nне перезаписывать существующие файлы
  • -tцелевой каталог

Как сценарий:

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

Запустите его как:

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

Связанный контент