異なるリスト内の行間に条件がある場合は、リストを解析して一致するものを見つけて、cpを使用してください。

異なるリスト内の行間に条件がある場合は、リストを解析して一致するものを見つけて、cpを使用してください。

誰でも私に何をすべきかを提案できますか?

2つのリスト(両方とも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(行2list01.txtと3 list02.txt)。 ファイル名とパス
にはスペースや特殊文字を含めることができます(例: ' " [ ](){}
など... )。. その前にスペースがあります。 list01.txt,sha1sumlist02.txtsha1sum /

この質問のタイトルからわかるように、if条件Bashスクリプトで一致するものがあるかどうかを確認してください。sha1sum はファイル名と同じです。)そしてそれを見つけたら、以下を使って各項目をコピーします。

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


ありがとうございます!

ベストアンサー1

仮定:

  • GNUツールが存在します(非標準xargscpオプション、他のNUL区切り文字は機能しない可能性がありますawk
  • ハッシュ値の長さは常に40文字です。
  • ハッシュとファイルパスを区別する2つの空白文字が常にあります。list02.txt
  • パイプ文字は両方のファイルに存在しません|(そうでない場合は別の区切り文字が使用されます)。

最初のステップは、2つのファイルをマージすることです。

join -t'|' -1 2 \
    <(sed -E 's/,(.{40})$/|\1/' list01.txt | sort -t'|' -k2) \
    <(sed -E 's/(.{40})  /\1|/' list02.txt | sort -t'|' -k1)
  • 最初のファイル:区切り文字を置き換えて、,2|番目のフィールドのファイルを並べ替えます。
  • 2番目のファイル:区切り文字 (2つのスペース)を最初のフィールドに置き換え、|最初のフィールドを並べ替えます。
  • ハッシュフィールドにファイルを追加する

出力:

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

おすすめ記事