Sendo um canalizador, gosto de cachimbos:)
Nota: essa resposta é detalhada - como uma novidade, eu agradeço quando alguém que sabe dedica seu tempo para explicar, então eu estou pagando 'para frente'. Se você não é um newbee, por favor, desculpe o comprimento e verbosidade.
ls -1 *_201[67][0-9]* | sed -e 's/\(\(.\+\)[-_]\(201[67][0-9]\{4\}\)\([^.]\+\)\?\.[0-9a-z]\{2,3\}\)/mkdir -p \/; mv \/\//' | bash
Onde:
ls -1 *_201[67][0-9]*
lista todos os arquivos correspondentes ao padrão, neste caso estou procurando por arquivos com a data no nome do arquivo no formato 'YYYYMMDD'
sed -e 's/\(\(.\+\)[-_]\(201[67][0-9]\{4\}\)\([^.]\+\)\?\.[0-9a-z]\{2,3\}\)/mkdir -p \/; mv \/\//'
# : | | | | | | | |: :
# : |^2....^ ^3..................^^4.......^ |: :
# :^1..............................................................^: :
# /................filename.................pattern................./...mkdir...and....mv...command.../
^ 1: primeiro grupo de captura - o nome do arquivo inteiro
^ 2: 2º grupo de captura - a primeira parte do padrão de nome de arquivo
^ 3: 3º grupo de captura - a segunda parte do nome do arquivo - aqui, a data como 'AAAAMMDD'
^ 4: quarto grupo de captura - parte do nome do arquivo opcional entre a data e a extensão, e a própria extensão
Sooooo .... se eu tiver um arquivo chamado
CallLog_555123412_20161231-214403.7z
... então
mkdir -p \/; mv \/\/
na verdade significa
# make directory and sub-directory
mkdir -p CallLog_555123412/20161231
# move file from current directory to sub-sub-directory just created
mv CallLog_555123412_20161231-214403.7z CallLog_555123412/20161231/CallLog_555123412_20161231-214403.7z
Observe que a saída do comando sed é redirecionada para 'bash' para executá-lo. Para primeiro ver o arquivo proposto se mover sem realmente movê-los, primeiro remova o '| bash 'no final e tente assim:
ls -1 *_201[67][0-9]* | sed -e 's/\(\(.\+\)[-_]\(201[67][0-9]\{4\}\)\([^.]\+\)\?\.[0-9a-z]\{2,3\}\)/mkdir -p \/; mv \/\//'
Isso não fará nenhuma alteração, mas você verá o comando que será executado SE você executá-lo com '| bash 'marcou no final.
Isso é útil porque você pode criar qualquer subdiretório que desejar em partes do nome do arquivo ou qualquer outra coisa adicionada ao texto 'replacement' no comando sed. Note que o sed exige muitos caracteres de escape.
colchetes Regex SED:
(...) exige escape para o agrupamento de captura - > \ (... \)
{m, n} exigem escape para quantificar o objeto anterior - > \ {m, n \}
/ requer escape na string de substituição - > \ /
[...] NÃO requer escape para classes de caracteres
\ 1 na string de substituição refere-se ao 1º grupo capturado, e assim por diante ...
AVISO DE SEGURANÇA: NUNCA TUBE NADA PARA 'bater', A MENOS QUE VOCÊ COMPREENDA INTEIRAMENTE O RESULTADO ...
Espero que ajude a eliminar alguns bloqueios:)