Pesquise um diretório recursivamente por arquivos listados em um csv e copie-os para outro local

3

Eu tenho um diretório (vamos chamá-lo de "Movies") que contém muitos arquivos e pastas. Eu tenho uma longa lista de nomes de arquivos em um arquivo .csv (cerca de 4000 entradas) que se referem a arquivos que estão localizados em algum lugar dentro das subpastas do diretório Movies.

Como posso pesquisar o diretório Filmes recursivamente para os arquivos listados no .csv e copiá-los para um diretório separado ("Sorted_Media")?

EDIT: Oi, eu anexei uma seção de exemplo do csv. Existem duas colunas de dados (de uma planilha eletrônica), que são separadas por um delimitador de vírgula no .csv. A primeira coluna de nomes de arquivos são os que eu preciso pesquisar (ou seja, NÃO os nomes de arquivos KA *). Alguns dos nomes de arquivos têm espaços, então isso é algo que precisa ser considerado como outra pessoa apontada.

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
    
por neilH 25.02.2016 / 18:36

3 respostas

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

Isso pressupõe que os nomes de arquivos não contenham caracteres curinga ( ? , [ , * ou backslash).

    
por 25.02.2016 / 18:51
1

Digamos que, por exemplo, o CSV seja assim:

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

Você pode fazer algo como:

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

Com zsh , você poderia fazer:

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/

Explicado:

  • cut -d , -f1 < movies.csv : recupera a primeira coluna do csv (um nome de arquivo por linha).
  • ${(f)"$(cmd)"} : divida a saída de cmd nos feeds de linha ( $files agora é uma matriz com todos os nomes de arquivos).
  • glob=('$files['{1..$#files}']') : cria outra matriz com elementos literalmente $files[1] , $files[2] ...
  • ${(j:|:)array} : junte os elementos da matriz com | , então estamos basicamente avaliando o comando tocopy=(Movies/**/($files[1]|$files[2]|...|$files[n])(DN.)) (onde n é o número de elementos na matriz $files ).
  • **/ : globalização recursiva (procure pelos arquivos em qualquer nível de subdiretórios).
  • (D.) : qualificadores glob (procure em diretórios ocultos também (D), somente arquivos regulares (.))

Ou com ferramentas 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='
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/
' ORS='
find Movies -type f -print0 |
  awk '
    !d {f[$1]; next}
    $NF in f {
      delete f[$NF]
      print
    }' FS=, file.csv d=1 FS=/ RS='%pre%' ORS='%pre%' - |
  xargs -r0 cp -vt Sorted_Media/
' - | xargs -r0 cp -vt Sorted_Media/

Usando delete , garantimos que apenas a primeira instância (se houver vários arquivos com o mesmo nome) seja copiada. -i na solução zsh é para lhe dar uma chance de decidir o que fazer se houver um conflito. Não podemos usar -i aqui porque o stdin de cp não é mais o terminal.

Substitua cp por echo cp se você quiser apenas verificar o que estaria fazendo sem realmente fazer isso.

    
por 25.02.2016 / 19:05