csvにリストされているファイルをディレクトリから繰り返し検索し、別の場所にコピーします。

csvにリストされているファイルをディレクトリから繰り返し検索し、別の場所にコピーします。

多くのファイルとフォルダを含むディレクトリ(「映画」と呼ばれる)があります。 Moviesディレクトリのサブフォルダのどこかにあるファイルを参照する.csvファイルに、非常に長いファイル名のリスト(約4000項目)があります。

Moviesディレクトリで.csvにリストされているファイルを繰り返し検索して別のディレクトリ(「Sorted_Media」)にコピーするにはどうすればよいですか?

編集:こんにちは。 CSVのサンプル部分を添付しました。 .csv には、コンマ区切り文字で区切られた 2 つのデータ列 (スプレッドシートの) があります。ファイル名の最初の列は、検索する必要があるファイル名です(つまり、KA *ファイル名ではありません)。一部のファイル名にはスペースがあるため、他の人が指摘したようにこれを考慮する必要があります。

preservation stocklshots - 16ln916-963.mp4,KA0003773-002.mp4
Preservation Stockshots_ 16LN916-963.mp4,KA0003773-001.mp4
Preservation Stockshots_16LN679-738.mp4,KA0003775-002.mp4
PreservationStockshots_16LN679_738.mp4,KA0003775-001.mp4
Preservation Stockshots_16LN01-52.mp4,KA0003776-002.mp4
Preservation_Stockshots_16LN01_52.mp4,KA0003776-001.mp4
Preservation Stockshots_LN566-LN624.mp4,KA0004507-001.mp4
PreservationStockShots_LN566_LN624.mp4,KA0004507-002.mp4
Preservation Stockshots_LN675-LN705.mp4,KA0004508-001.mp4
PreservationStockshots_LN675_LN705.mp4,KA0004508-002.mp4
Preservation Stockshots_LN706-752.mp4,KA0004509-001.mp4
PreservationStockshots_LN706_LN752.mp4,KA0004509-002.mp4
Preservation Stockshots_LN930-LN972.mp4,KA0004511-001.mp4
PreservationStockShots_LN930_LN972.mp4,KA0004511-002.mp4
Preservation Stockshots_LN1023-LN1059.mp4,KA0004513-001.mp4
PreservationStockShots_LN1023_LN1059.mp4,KA0004513-002.mp4
Preservation Stockshots_LN1152-LN1220.mp4,KA0004515-001.mp4
PreservationStockShots_LN1152_LN1220.mp4,KA0004515-002.mp4
Preservation Stockshots_16LN320-379.mp4,KA0004517-001.mp4
Preservation_Stockshots_16LN320_379.mp4,KA0004517-002.mp4

答え1

while IFS=, read -r file rest
do
  find /path/to/movies_dir -name "${file}" -exec cp '{}' /path/to/Sorted_Media/ \;
done < mylist.csv

ファイル名にはワイルドカード文字(または?バックスラッシュ)が含まれていないと想定されます。[*

答え2

たとえば、CSVは次のようになります。

Spaceballs,/mnt/Movies/Comedy/Spaceballs.avi
Star Wars IV: A New Hope,/mnt/Movies/SciFi/starwars-4.avi

これにより、次のことができます。

#!/bin/bash
DEST=/path/to/SortedMedia
for file in $( cut -d, -f 2 /path/to/movielist.csv ); do
    cp "$file" $DEST/"${file##*/}"
done

答え3

これにより、zsh次のことができます。

files=(${(f)"$(cut -d , -f 1 <movies.csv)"})
glob=('$files['{1..$#files}']')
eval "tocopy=(Movies/**/(${(j:|:)glob})(D.))"
print -rl -- $tocopy # to  check it's OK
cp -i -- $tocopy Sorted_Media/

説明する:

  • cut -d , -f1 < movies.csv:csvの最初の列を検索します(1行あたり1つのファイル名)。
  • ${(f)"$(cmd)"}cmd:改行で出力を分割します($filesすべてのファイル名を含む配列)。
  • glob=('$files['{1..$#files}']'):リテラル要素を使用して別の配列を作成します$files[1]$files[2]...
  • ${(j:|:)array}:要素が配列に追加されたので、基本的|にコマンドを評価しますtocopy=(Movies/**/($files[1]|$files[2]|...|$files[n])(DN.))n配列の要素数はどこにあります$files)。
  • **/:再帰的グロービング(すべてのレベルのサブディレクトリにあるファイルを検索)。
  • (D.):glob修飾子(隠しディレクトリ(D)でも検索し、一般ファイル(.)でのみ検索)

またはGNUツールを使用してください。

find Movies -type f -print0 |
  awk '
    !d {f[$1]; next}
    $NF in f {
      delete f[$NF]
      print
    }' FS=, file.csv d=1 FS=/ RS='\0' ORS='\0' - |
  xargs -r0 cp -vt Sorted_Media/

を使用すると、delete最初のインスタンスのみがコピーされます(同じ名前のファイルが複数ある場合)。-izshソリューションの機能を使用すると、競合が発生した場合の対処方法を決定できます。のstdinはもはや端末ではない-iため、ここでは使用できません。cp

実際に実行せずに何をするのかを確認したい場合は、に変更してcpください。echo cp

関連情報