Mover arquivos lendo seus nomes de arquivos em diretórios diferentes

1

Eu preciso mover os arquivos lendo seus nomes. Eu tenho que mover arquivos gerados pelo sistema e os nomes incluem um carimbo de hora. Eu preciso mover os arquivos lendo o nome do arquivo por mês.

Se o nome do arquivo contiver 201601*.txt , mova para o diretório 2016/January . Se o nome do arquivo contiver 201602*.txt , mova para o diretório 2016/February , etc.

    
por user1924765 20.06.2016 / 11:35

3 respostas

2

Bem, se as strings de data estiverem nos nomes dos arquivos e todos os arquivos estiverem no mesmo diretório, você poderia fazer:

mv 201601*.txt 2016/January

Fazer isso 12 vezes manualmente seria uma dor, então eu criaria uma lista com o número e o nome do mês correspondente:

$ paste <(printf '%s\n' {01..12}) <(cal 2016 | grep -Po '\s+\K[A-Z]\w{2,}') 
01  January
02  February
03  March
04  April
05  May
06  June
07  July
08  August
09  September
10  October
11  November
12  December

Em seguida, analise-o para criar os comandos mv :

$ paste <(printf '%s\n' {01..12}) <(cal 2016 | grep -Po '\s+\K[A-Z]\w{2,}') | 
    while read num month; do echo mv "*2016$num*" 2016/"$month"; done
mv *201601* 2016/January
mv *201602* 2016/February
mv *201603* 2016/March
mv *201604* 2016/April
mv *201605* 2016/May
mv *201606* 2016/June
mv *201607* 2016/July
mv *201608* 2016/August
mv *201609* 2016/September
mv *201610* 2016/October
mv *201611* 2016/November
mv *201612* 2016/December

Quando tiver certeza de que faz o que precisa, remova o echo para realmente mover os arquivos:

paste <(printf '%s\n' {01..12}) <(cal 2016 | grep -Po '\s+\K[A-Z]\w{2,}') | 
    while read num month; do echo mv "*2016$num*" 2016/"$month"; done

Explicação

O grep -Po '\s+\K[A-Z]\w{2,}') executará grep com expressões regulares compatíveis com Perl ( -P ) e imprimirá apenas a (s) parte (s) correspondente (s) de cada linha ( -o ). A expressão regular usada procurará por um ou mais caracteres de espaço em branco ( \s+ ) seguidos por uma letra maiúscula ( [A-Z] ) e 2 ou mais caracteres de palavra ( \w{2,} ). O \K significa "ignorar tudo antes disso", o que fará com que o comando apenas imprima a parte das sequências correspondentes após o espaço em branco. A coisa toda simplesmente imprime a lista de meses.

    
por 20.06.2016 / 12:06
1

Zsh tem uma função interessante para renomear arquivos baseados em padrões de nomes: zmv . No padrão de substituição, $f designa todo o nome original e $1 , $2 etc. são os grupos entre parênteses. Use uma matriz para armazenar os nomes dos meses.

autoload -U zmv
months=(January February March April May June July August September October November December)
zmv '(2016)(<1-12>)*.txt' '$1/$months[$2]/$f'

Como o padrão aqui é simples, não é muito difícil adaptar isso para o bash e o ksh, com um loop. Você precisa cuidar de algumas coisas: tire o 0 inicial do número do mês para que não seja interpretado como octal; índices de matriz começam em 0.

months=(January February March April May June July August September October November December)
for f in 2016[0-9][0-9]*; do
  y=${f:0:4} m=${f:4:2}
  mv -- "$f" "$y/${months[${m#0}]}/$f"
done

Outra abordagem é o script de renomeação Perl (ou a versão Debian ou a Unicode::Tussle version ).

rename 'BEGIN {@months = qw(January February March April May June July August September October November December)}
        s!^([0-9]{4})([0-9]{2})!$1/$months[$2]/&!' 2016[0-9][0-9]*
    
por 21.06.2016 / 01:51
0

Aqui está uma solução bash que executa os arquivos, movendo aqueles que correspondem ao componente yyyymm (para valores de yyyy no intervalo 2000-2099):

months=('' January February March April May June July August September October November December)

for f in 20[0-9][0-9][0-3][0-9]*
do
    year=$(echo "$f" | grep -Po '^20\d\d')           # Extract the four digit year, 20nn
    mm=$(echo "$f" | grep -Po '^(?<=20\d\d)\d\d')    # Find the two digit month number 01-12
    month=${months[$mm]}                             # Convert to a month name

    test -n "$year" -a -n "$month" && echo mv "$f" "$yyyy/$month/$f"
done

Remova o prefixo echo do mv quando estiver pronto para executar.

Se você sabe que todos os arquivos começam com 2016 , você pode simplificar um pouco o processamento:

for f in 2016[0-3][0-9]*
do
    mm=$(echo "$f" | grep -Po '^(?<=2016)\d\d')    # Find the two digit month number 01-12
    month=${months[$mm]}                           # Convert to a month name

    test -n "$month" && echo mv "$f" "2016/$month/$f"
done
    
por 21.06.2016 / 00:51