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/date
diretó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 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 expansão de parâmetro para extrair a data: ${dt}
e o ID do usuário: ${id}
do nome do arquivo e depois usainstall
copiar cada arquivo para o userID/date
diretório correspondente (isso é porque 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 um loop nesses diretórios de "data" e depois nos .WAV
arquivos 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
, $2
etc.
Aqui zmv
with -p
executa a função dtcp
em 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 -n
significafuncionamento a seco; remova-o para realmente executar o comando.