O arquivo em lote é movido para a estrutura de diretórios com base no nome do arquivo

1

Estou escrevendo um script para mover arquivos para diretórios com base no nome do arquivo. Os arquivos têm yyyyddmm-xxxxxxx.jpg formato de nome. A estrutura de diretórios desejada está no formato 2013/01 Jan/31 . Não é possível obter date para formatar corretamente com um espaço entre o número do mês e o nome do mês. Quando tento usar o formato +%Y/%m %b , recebo esta mensagem de erro:

date: extra operand '%b"'

Eu tentei aspas duplas e simples, mas sem sucesso. No entanto, date +"%Y/%m %b/%d" funciona bem em sh :

2013/10/27 Oct

Além disso, existe uma maneira melhor de gerar o nome do diretório do que usando as variáveis MOVEDIRSTR e MOVEDIR (consulte o script)?

Este é o meu script atual:

FLIST='ls "$IMGDIR" | grep -E '^.*\.jpg$''

# If there are files to move
if [ -n "${FLIST}" ]; then
    # For each file
    while read -r line; do
        # Parse filename to YYYY/mm Mmm/Dd
        echo $line
        MOVEDIRSTR='sed -r -e 's:([0-9]{4})([0-9]{2})([0-9]{2}).*:date -d -- +%Y/%m_%b/%d:' <<< "$line"'
        MOVEDIR='$MOVEDIRSTR'

        # If a directory does not exist, create it
        [ -d "$ARCHIVEDIR/$MOVEDIR" ] || (mkdir -p "$ARCHIVEDIR/$MOVEDIR")

        # Move file into YYYY/mm Mmm directory
        # mv -f "$IMGDIR/$line" "$ARCHIVEDIR/$MOVEDIR"
    done <<< "$FLIST"
fi
    
por Serge 27.10.2013 / 05:28

3 respostas

1

Você precisa citar o formato para a data após o sinal + .

$ date +"%Y/%m %b"
2013/10 Oct

Em relação às variáveis. $MOVEDIRSTR parece desnecessário.

MOVEDIR=$(sed -r -e 's:([0-9]{4})([0-9]{2})([0-9]{2}).*:date -d -- +%Y/%m_%b/%d:' <<< "$line")

Já que com $FLIST você está analisando as datas desse diretório, não vejo uma maneira mais clara.

UPDATE # 1

Dado o feedback do OP nos comentários abaixo, ele está usando um dispositivo QNAP e provavelmente tem uma versão diluída desses comandos fornecidos pelo BusyBox. Se você olhar o comando date assim: ls -l /bin/date é provavelmente um link para um executável chamado busybox ou algo semelhante. Esses comandos não são completos, por isso seus problemas.

Ele confirmou isso:

You're probably right. My date is its own executable, but /bin/sed -> busybox

Dadas as limitações, os métodos discutidos acima podem não funcionar, pois você está trabalhando com um conjunto limitado de recursos com essas ferramentas.

    
por 27.10.2013 / 05:58
1

Primeiro de tudo, eu usaria um glob para evitar analisar ls e obter a lista de arquivos .jpg nessa rotatória caminho. Segundo, você pode usar o próprio shell (sem necessidade de sed ) para extrair os componentes de data:

shopt -s nullglob
for file in "$IMGDIR"/*.jpg; do
    file_name="$(basename file)"
    printf "%s\n" "$file_name"
    numbers="${file%-*}"
    year="${numbers%[0-9][0-9][0-9][0-9]}"
    monthday="${numbers#[0-9][0-9][0-9][0-9]}"
    month="${monthday%[0-9][0-9]}"
    day="${monthday#[0-9][0-9]}"
    movedir="$(date -d "$year-$month-$day" +"%Y/%m %b/)"
    movefile="$(date -d "$year-$month-$day" +"%Y/%m %b/%d)"
    [ -d "$ARCHIVEDIR/$movedir" ] || mkdir -p "$ARCHIVEDIR/$movedir"
    mv "$file" "$movefile"
done

Isso pressupõe, é claro, que o comando date tenha um conjunto de recursos suficiente, já que você mencionou que é um executável separado do BusyBox. Ele também será quebrado se sua string de data não tiver exatamente 8 dígitos.

    
por 27.10.2013 / 10:29
1

veja se o seguinte poderia resolver a extração de data e a parte de formatação:

$ f=20130131-abcdefgh.jpg
$ [[ $f =~ ^([[:digit:]]{4})([[:digit:]]{2})([[:digit:]]{2}) ]]
$ yyyy=${BASH_REMATCH[1]}
$ mm=${BASH_REMATCH[2]}
$ dd=${BASH_REMATCH[3]}
$ date -d ${yyyy}-${mm}-${dd} +'%Y/%m %b/%d'
2013/01 Jan/31
    
por 27.10.2013 / 10:40