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.