많은 파일과 폴더가 포함된 디렉터리("영화"라고 함)가 있습니다. 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
첫 번째 인스턴스만 복사됩니다(동일한 이름을 가진 파일이 여러 개 있는 경우). -i
zsh 솔루션의 기능을 사용하면 충돌이 발생할 경우 수행할 작업을 결정할 수 있습니다. 의 stdin은 더 이상 터미널이 아니기 -i
때문에 여기서는 사용할 수 없습니다 .cp
실제로 실행하지 않고 단지 무엇을 할지 확인하고 싶다면 cp
로 바꾸세요.echo cp