請問有人可以建議我該怎麼做嗎?
我有兩個清單(都帶有 sha1sum 及其相對檔案名稱),但格式不同,以下是一個範例:
列表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...]
如您所看到的,唯一好的條目是55a5fdde4843fc2f9d9e691cb658b6389d698b22
帶有檔案名稱的sha1sum hello(previous one).sh
(第 2 行list01.txt
和第 3 行list02.txt
)。
檔案名稱和路徑可以包含空格和特殊字元(例如:' " [ ] ( ) { } 等等...)。
唯一 100% 確定的是它list01.txt
始終格式化為,sha1sum
; 並且list02.txt
始終有sha1sum /
(兩個/) 之前有空格。
正如這個問題的標題所示,我想使用if 條件在 bash 腳本中檢查兩個清單以查找匹配項(TRUE 是 ifsha1sum 和檔案名稱相同),當它找到它們時,將使用複製每個出現的情況
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