递归搜索目录以查找 csv 中列出的文件,并将它们复制到另一个位置

递归搜索目录以查找 csv 中列出的文件,并将它们复制到另一个位置

我有一个目录(我们称之为“电影”),其中包含许多文件和文件夹。我在 .csv 文件中有一个很长的文件名列表(大约 4000 个条目),它们引用位于 Movies 目录子文件夹中某处的文件。

如何在 Movies 目录中递归搜索 .csv 中列出的文件并将它们复制到单独的目录(“Sorted_Media”)?

编辑:嗨,我已附上 csv 的示例部分。 .csv 中有两列数据(来自电子表格),由逗号分隔符分隔。第一列文件名是我需要搜索的文件名(即不是 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 的第一列(每行一个文件名)。
  • ${(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 解决方案中的功能是让您有机会决定发生冲突时该怎么做。我们不能-i在这里使用,因为cp's stdin 不再是终端。

如果您只是想检查它会做什么而不实际执行它,请替换cp为。echo cp

相关内容