Classificando arquivos em pastas com base na data no nome do arquivo?

1

Resolvido: veja as atualizações nos comentários.

Estou tentando classificar arquivos com uma data no nome do arquivo em pastas com base nessa data. Os arquivos costumavam ter um espaço no nome do arquivo, como este. Existem alguns arquivos mais antigos, então eu preciso classificá-los também.

Envio de fax_20180521121901.pdf

Agora estamos obtendo os arquivos sem espaço no nome do arquivo, por isso é apenas Dispatch_20180521124202.pdf

A data é 20180521 e o resto eu acho que são IDs de mensagens, mas não precisamos disso. Apenas a data.

Esta tentativa de um script bash (caixa do Ubuntu 18.04) acabou criando uma única pasta chamada 2018-05-21, um nível de diretório acima de onde os arquivos viviam, e apenas colocou todos os arquivos pdf naquela pasta.

    for x in /home/tb/temp/*.pdf
do
    d=$(date -r "$x" +%Y-%m-%d)
    mkdir -p "$d"
    mv -- "$x" "$d/"
done

Isso acabou mudando para uma pasta chamada "e" de alguma forma.

for x in /home/tb/temp/*.pdf
do
    d="${x:4:4}-${x:8:2}-${x:10:2}"
    mkdir -p "$d"
    mv -- "$x" "$d/"
done

Esta tentativa? Acabei com uma pasta para cada PDF.

/home/tb/20180521124202.pdf/Dispatch Fax_20180521124202.pdf /home/tb/20180521121901.pdf/Dispatch Fax_20180521121901.pdf

for x in /home/tb/temp/*.pdf
do
    d=$(echo "$x" | awk -F _ '{print $2}')
    mkdir -p "$d"
    mv -- "$x" "$d/"
done

Os scripts são de posts anteriores aqui e aqui e aqueles trabalharam para eles, mas eu não estou tendo a mesma sorte, mesmo que o objetivo seja o mesmo.

Meu objetivo é preencher um diretório temporário do rsync (puxando esses arquivos de outro servidor) e, em seguida, via cron, executar esse script para mover coisas para pastas com base na data e exibi-las via Apache com "Opções + Índices". " ativado. É uma página única da intranet e esta máquina em particular não tem acesso externo. Estrutura de diretórios é simples. Eventualmente algo como / var / www / html / 2018/5/21 etc, seguindo o formato AAAA / MM / DD.

Eu estou apenas em uma perda de como conseguir este trabalho e meu conhecimento de script bash é muito enferrujado. Eu olhei alguns outros exemplos como este um mas depois vejo que não funcionará com arquivos que tenham espaços nos nomes de arquivos.

Estou aberto a ideias!

    
por Taco Bob 22.05.2018 / 02:01

2 respostas

2

Sua pergunta não está totalmente clara para mim, mas acho que posso entender o que você está tentando fazer.

Aqui está o loop que você está usando:

for x in /home/tb/temp/*.pdf
do
    d="${x:4:4}-${x:8:2}-${x:10:2}"
    mkdir -p "$d"
    mv -- "$x" "$d/"
done

Os nomes de arquivos de exemplo que você deu foram:

  1. Dispatch Fax_20180521121901.pdf
  2. Dispatch_20180521124202.pdf

Um problema para mim é que sua expressão de substituição de parâmetro ( d="${x:4:4}-${x:8:2}-${x:10:2}" ) não parece produzir os resultados corretos, por exemplo:

> x='Dispatch Fax_20180521121901.pdf'
> d="${x:4:4}-${x:8:2}-${x:10:2}"
> echo ${d}
atch- F-ax

> x='Dispatch_20180521124202.pdf'
> d="${x:4:4}-${x:8:2}-${x:10:2}"
> echo ${d}
atch-_2-01

Você pode tentar usar grep , por exemplo:

> x='Dispatch Fax_20180521121901.pdf'
> d=$(echo "${x}" | grep -Po '\d{8}')
> echo ${d}
20180521

> x='Dispatch Fax_20180521121901.pdf'
> d=$(echo "${x}" | grep -Po '\d{8}')
> echo ${d}
20180521

Ou, se você quiser adicionar hífens, poderá usar a seguinte substituição de comando sed -based:

> x='Dispatch Fax_20180521121901.pdf'
> d=$(echo "${x}" | sed -E 's/^[^0-9]*([0-9]{4})([0-9]{2})([0-9]{2}).*$/--/')
> echo ${d}
2018-05-21

> x='Dispatch Fax_20180521121901.pdf'
> d=$(echo "${x}" | sed -E 's/^[^0-9]*([0-9]{4})([0-9]{2})([0-9]{2}).*$/--/')
> echo ${d}
2018-05-21

Supondo que esse é o resultado desejado (ou seja, se você deseja subdiretórios do formato %Y-%m-%d ), poderíamos substituir sua expressão de substituição de parâmetro pela substituição de comando grep -based. Isso nos daria o seguinte loop modificado:

for filename in /home/tb/temp/*.pdf; do
    datestring=$(echo "${filename}" | sed -E 's/^[^0-9]*([0-9]{4})([0-9]{2})([0-9]{2}).*$/--/')
    mkdir -p "${datestring}"
    mv -i -- "${filename}" "${datestring}/"
done

Isso deve produzir subdiretórios da forma %Y-%m-%d e preenchê-los com os arquivos apropriados.

UPDATE: Com base no seu comentário, parece que o que você deseja são subdiretórios aninhados no formulário %Y/%m/%d . Para isso, você precisaria extrair as substrings de ano, mês e dia separadamente, por exemplo:

> x='Dispatch Fax_20180521121901.pdf'
> d=$(echo "${x}" | grep -Po '\d{8}')
> year=${d:0:4}
> month=${d:4:2}
> day=${d:6:2}
> echo "${year}/${month}/${day}/"
2018/05/21/

Isso nos leva ao seguinte loop:

for filename in /home/tb/temp/*.pdf; do
    datestring=$(echo "${filename}" | grep -Po '\d{8}')
    year=${datestring:0:4}
    month=${datestring:4:2}
    day=${datestring:6:2}
    directory="${year}/${month}/${day}/"
    mkdir -p "${directory}"
    mv -i -- "${filename}" "${directory}"
done
    
por 22.05.2018 / 02:34
1

Se você não precisa lidar com nomes de arquivos ativamente hostis,

sed -E 's/([0-9]{0,7}[^0-9]+)*([0-9]{8}).*/mkdir -p ; mv "&" /e'
#         111111111111111111 2222222222 

O padrão é zero a sete dígitos seguidos por alguns não-dígitos, qualquer número de vezes, seguido por 8 dígitos, uma vez. O segundo padrão, o de 8 dígitos, corresponde à data.

Se você não tem o GNU sed, você pode, ao invés do flag e , transformar o resultado em um shell.

    
por 22.05.2018 / 02:36