제발, 누구든지 친절하게 나에게 어떻게 해야할지 제안해 줄 수 있습니까?
두 개의 목록(둘 다 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
형식이며 항상 (두 개) / 앞에 공백이 있습니다.
,sha1sum
list02.txt
sha1sum /
이 질문의 제목과 같이if 조건일치하는 항목을 찾기 위해 두 목록을 모두 확인하는 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의 파일 이름이 마지막 필드의 파일 이름으로 존재하는지 테스트하는 데 사용합니다 . 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