O que é uma maneira mais rápida de extrair o ano de nomes de arquivos para movê-los para diretórios baseados no ano do que minha abordagem atual de usar 'cut' e 'rev'?

3

Eu tenho uma aplicação web que acessa um armazenamento remoto rodando Linux para pegar alguns arquivos, o problema é que o armazenamento remoto tem atualmente 3 milhões de arquivos, então acessar o caminho normal é um pouco complicado.

Então, eu precisava trabalhar em um script que tornasse um pouco mais fácil de usar, esse script vai reorganizar os arquivos em várias pastas, dependendo da data de criação deles e especialmente dos nomes deles, eu fiz o script e funcionou muito bem, pretendia fazer o que pretendia fazer, mas era muito lento, 12 horas para executar o trabalho completamente (12:13:48 to be precise) .

Acho que a lentidão vem das várias chamadas cut e rev que faço.

exemplo :

Eu obtenho os nomes dos arquivos com um comando ls com o qual eu faço um loop, e para cada arquivo eu obtenho o diretório pai e, dependendo do diretório pai, posso obter o ano correto:

 case "$parent" in
                ( "Type1" )
                year=$(echo "$fichier" | rev | cut -d '_' -f 2 | rev );;

                ( "Type2" )
                year=$(echo "$fichier" | rev | cut -d '_' -f 2 | rev);;

                ( "Type3" )
                year=$(echo "$fichier" | rev | cut -d '_' -f 1 | rev | cut -c 1-4);;

                ( "Type4" )
                year=$(echo "$fichier" | rev | cut -d '_' -f 1 | rev | cut -c 1-4);;

                ( "Type5" )
                year=$(echo "$fichier" | rev | cut -d '_' -f 1 | rev | cut -c 1-4);;
                esac

para type1 de arquivos:

the file==>MY_AMAZING_FILE_THAT_IMADEIN_YEAR_TY.pdf

Eu preciso pegar o ano para fazer um corte reverso:

year=$(echo "$file" | rev | cut -d '_' -f 2 | rev );;

para type2 de arquivos:

the file==>MY_AMAZING_FILE_THAT_IMADE_IN_YEAR_WITH_TY.pdf 

etc ...

e depois eu posso mv o arquivo livremente: mv $file /some/path/destination/$year/$parent

e ainda assim é o exemplo mais simples, existem alguns arquivos que são muito mais complexos, então, para obter 1 informação eu preciso fazer 4 operações, 1 echo , 2rev and 1echo .

Enquanto o script está em execução, estou obtendo velocidades de 50 files/sec to 100 files\s . Recebi essa informação fazendo wc-l output.txt do script.

Existe algo que eu possa fazer para torná-lo mais rápido? ou outra maneira de cortar o nome dos arquivos? Eu sei que posso usar sed ou awk ou operações de string, mas eu realmente não entendi como.

    
por Kingofkech 11.10.2017 / 15:20

2 respostas

6

Para obter a parte YEAR do nome do arquivo MY_AMAZING_FILE_THAT_IMADEIN_YEAR_TY.pdf sem usar utilitários externos:

name='MY_AMAZING_FILE_THAT_IMADEIN_YEAR_TY.pdf'

year=${name%_*}    # remove everything after the last '_'
year=${year##*_}   # remove everything up to the last (remaining) '_'

Após a atualização da pergunta:

Movendo arquivos PDF de topdir para um diretório /some/path/destination/<year>/<parent> , em que <year> é o ano encontrado no nome do arquivo, e <parent> é o nome base do diretório original em que o arquivo foi encontrado:

find topdir -type f -name '*.pdf' -exec bash ./movefiles.sh {} +

movefiles.sh é um script de shell no diretório atual:

#!/bin/bash

destdir='/some/path/destination'

for name; do
    # get basename of directory
    parent=${name%/*}
    parent=${parent##*/}

    # get the year from the filename:
    #  - Pattern:  _YYYY_         (in the middle somewhere)
    #  - Pattern:  _YYYYMMDD.pdf  (at end)
    if [[ "$name" =~ _([0-9]{4})_ ]] ||
       [[ "$name" =~ _([0-9]{4})[0-9]{4}\.pdf$ ]]; then
        year="${BASH_REMATCH[1]}"
    else
        printf 'No year in filename "%s"\n' "$name" >&2
        continue
    fi

    # make destination directory if needed
    # (remove echo when you have tested this at least once)
    if [ ! -d "$destdir/$year/$parent" ]; then
        echo mkdir -p "$destdir/$year/$parent"
    fi

    # move file
    # (remove echo when you have tested this at least once)
    echo mv "$name" "$destdir/$year/$parent"
done
    
por 11.10.2017 / 15:27
2

Você pode aplicar a abordagem sed para extrair o valor year :

year=$(sed -E 's/.*_([0-9]{4})_TY\.pdf//' <<<"$file")
    
por 11.10.2017 / 15:27

Tags