誰でも私に何をすべきかを提案できますか?
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
,sha1sum
list02.txt
sha1sum /
この質問のタイトルからわかるように、if条件Bashスクリプトで一致するものがあるかどうかを確認してください。sha1sum はファイル名と同じです。)そしてそれを見つけたら、以下を使って各項目をコピーします。
cp $source $destination
source=reads the /path/to/filename from list02.txt
destination=/wherever/i/want/
ありがとうございます!
ベストアンサー1
仮定:
- GNUツールが存在します(非標準
xargs
とcp
オプション、他の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番目のファイル:区切り文字
|
最初のフィールドを並べ替えます。 - ハッシュフィールドにファイルを追加する
出力:
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