다른 목록 내의 줄 사이에 조건이 있는 경우 목록에서 일치하는 항목을 구문 분석한 다음 cp를 사용하세요.

다른 목록 내의 줄 사이에 조건이 있는 경우 목록에서 일치하는 항목을 구문 분석한 다음 cp를 사용하세요.

제발, 누구든지 친절하게 나에게 어떻게 해야할지 제안해 줄 수 있습니까?

두 개의 목록(둘 다 sha1sum 및 해당 상대 파일 이름 포함)이 있지만 형식이 다릅니다. 예는 다음과 같습니다.
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...]


보시다시피, 유일하게 좋은 항목은 55a5fdde4843fc2f9d9e691cb658b6389d698b22파일 이름이 있는 sha1sum hello(previous one).sh( 의 두 번째 줄 list01.txt과 세 번째 줄 list02.txt)입니다.
파일 이름과 경로에는 공백과 특수 문자가 포함될 수 있습니다(예: ' " [ ] ( ) { } 등...).
100% 확신할 수 있는 유일한 것은 항상 ; list01.txt형식이며 항상 (두 개) / 앞에 공백이 있습니다. ,sha1sumlist02.txtsha1sum /

이 질문의 제목과 같이if 조건일치하는 항목을 찾기 위해 두 목록을 모두 확인하는 bash 스크립트에서(TRUE는 다음과 같습니다.sha1sum과 파일 이름이 모두 동일합니다.) 그리고 이를 찾으면 다음을 사용하여 모든 항목을 복사합니다.

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


감사해요!

답변1

가정:

  • GNU 도구가 있습니다(비표준 xargscp옵션, 다른 의 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의 파일 이름이 마지막 필드의 파일 이름으로 존재하는지 테스트하는 데 사용합니다 . true인 경우 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

관련 정보