csv에 나열된 파일을 디렉터리에서 반복적으로 검색하고 다른 위치에 복사합니다.

csv에 나열된 파일을 디렉터리에서 반복적으로 검색하고 다른 위치에 복사합니다.

많은 파일과 폴더가 포함된 디렉터리("영화"라고 함)가 있습니다. Movies 디렉터리의 하위 폴더 어딘가에 있는 파일을 참조하는 .csv 파일에 매우 긴 파일 이름 목록(약 4000개 항목)이 있습니다.

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 솔루션의 기능을 사용하면 충돌이 발생할 경우 수행할 작업을 결정할 수 있습니다. 의 stdin은 더 이상 터미널이 아니기 -i때문에 여기서는 사용할 수 없습니다 .cp

실제로 실행하지 않고 단지 무엇을 할지 확인하고 싶다면 cp로 바꾸세요.echo cp

관련 정보