if 不同列表內的行之間的條件,解析列表以查找匹配項,然後使用 cp

if 不同列表內的行之間的條件,解析列表以查找匹配項,然後使用 cp

請問有人可以建議我該怎麼做嗎?

我有兩個清單(都帶有 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 工具(非標準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

相關內容