copia um grande número de arquivos em ordem de diretório estruturado de data

2

Eu preciso copiar cerca de 40.0000 arquivos em pastas estruturadas de datas.
arquivo de exemplo:

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

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

O nome do arquivo tem duas variáveis que eu preciso usar:

bbbbbb_I_20151209-185841_xxxxxx_12434_89343.WAV

20151209 é claro que a data em que 12434 é o id do usuário que fez o arquivo.

O que eu preciso é de um script / um forro que possa pesquisar em um diretório para 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, é necessário criar um diretório para cada data que encontrar.
E coloque todos os arquivos no diretório userid/date correto.
exemplo de resultado.

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

Eu construí um one-liner para fazer o diretório da data, mas eu ainda preciso fazer o id do usuário dir.

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 correto para o lugar certo?

    
por Wilde 20.05.2016 / 19:22

1 resposta

1

Uma maneira com find e 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 a expansão de parâmetro para extrair a data: ${dt} e o ID do usuário: ${id} do nome do arquivo e, em seguida, usa install para copiar cada arquivo para o diretório correspondente userID/date (isso é porque eu sou preguiçoso) - sem install substituir a última linha por:

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

Se você preferir fazer o loop sobre os diretórios "date" e, em seguida, executar um loop pelos arquivos .WAV 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 com zmv (também porque zsh é mais inteligente e você pode aninhar expansões 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'

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

    
por 20.05.2016 / 21:19