copie um grande número de arquivos em ordem de diretório estruturada por data

copie um grande número de arquivos em ordem de diretório estruturada por data

Preciso copiar cerca de 40.0000 arquivos em pastas estruturadas por datas.
arquivo de exemplo:

/var/public/voicelogging/quality_monitoring/20151209/bbbbbb_I_20151209-185841_xxxxxx_12434_89343.WAV

É um dos muitos arquivos para os quais preciso copiar/home/username/logging/

O nome do arquivo contém 2 variáveis ​​que preciso usar:

bbbbbb_I_20151209-185841_xxxxxx_12434_89343.WAV

20151209é claro que a data
12434é o ID do usuário que criou o arquivo.

O que eu preciso é de um script/um liner que possa pesquisar em um diretório o ID do usuário.

Em seguida, crie um diretório com o ID do usuário em /home/username/logging. Depois de criar a pasta, ele precisa criar um diretório para cada data que encontrar.
E coloque cada arquivo no userid/datediretório correto.
exemplo de diretório de resultado.

/home/username/logging/12434/20151209/bbbbbb_I_20151209-185841_xxxxxx_12434_89343.WAV

Eu criei uma linha única para criar os diretórios de data, mas ainda preciso criar o diretório de identificação do usuário sozinho.

find /var/public/voicelogging/quality_monitoring/ -type f -name "*12434*" | sed -r 's/^.{65}//' | cut -c1-8 | xargs -I {} mkdir {} /home/username/logging/12434

Como posso copiar o arquivo certo para o lugar certo?

Responder1

Uma maneira com finde install:

find /var/public/voicelogging/quality_monitoring -name \*.WAV -exec sh -c '
bn=${0##*/}; x=${bn%%-*}; dt=${x##*_}; y=${bn%_*}; id=${y##*_} 
install -D "$0" "/home/username/logging/${id}/${dt}/${bn}"' {} \;

isso usa expansão de parâmetro para extrair a data: ${dt}e o ID do usuário: ${id}do nome do arquivo e depois usainstallcopiar cada arquivo para o userID/datediretório correspondente (isso é porque sou preguiçoso) - sem installsubstituir a última linha por:

dest=/home/username/logging/${id}/${dt}; mkdir -p "${dest}" && cp "$0" "${dest}"' {} \;

Se você preferir fazer um loop nesses diretórios de "data" e depois nos .WAVarquivos em cada diretório:

for d in /var/public/voicelogging/quality_monitoring/*; do
  dt=${d##*/}
  for f in $d/*.WAV; do
    bn=${f##*/}; y=${bn%_*}; id=${y##*_}
    dest=/home/username/logging/${id}/${dt}
    mkdir -p "${dest}" && cp "${f}" "${dest}"
  done
done

Se você tiver, zshé mais fácil e mais curto zmv(também porque zshé mais inteligente e você pode aninhar expansões de variáveis, por exemplo, ${${file%_*}##*_}seria suficiente para extrair o ID do usuário):

dtcp () {                                                                     
mkdir -p $3 && cp $1 $2 $3
}
autoload zmv
zmv -n -p dtcp '/var/public/voicelogging/quality_monitoring/(*)/(*).WAV' \
'/home/username/logging/${${2%_*}##*_}/$1'

Os (*)s criam referências anteriores que podem ser usadas no segundo parâmetro como $1, $2etc.
Aqui zmvwith -pexecuta a função dtcpem vez de mv. A função cria o diretório e depois copia o arquivo para o diretório recém-criado. Os argumentos (não confundir com as referências anteriores acima) são:
$1: --
que significa fim das opções
$2: /var/public/voicelogging/quality_monitoring/(*)/(*).WAV'
esse é o arquivo que deve ser copiado e
$3: /home/username/logging/${${2%_*}##*_}/$1
qual é o destino
Nota que -nsignificafuncionamento a seco; remova-o para realmente executar o comando.

informação relacionada