Copia o arquivo para o destino com base no arquivo ini

2

Eu tenho alguns milhares de subdiretórios em um diretório, cada um contendo um arquivo config.ini e uma imagem JPEG. O arquivo ini contém (incluindo, mas não se limitando a) uma seção que codifica a hora, quando a imagem foi tirada.

[Acquisition]
Name=coating_filtered_001
Comment=Image acquisition
Year=2017
Month=3
Day=21
Hour=13
Minute=2
Second=34
Milliseconds=567

Os arquivos de imagem sempre têm o mesmo nome exato, por causa desta questão image.jpg .

Eu gostaria de copiar todos os arquivos de imagem para algum outro diretório (único) e renomeá-los para algo como yyyy-mm-ddThh:mm:ss:NNN.jpg ou similar, ou seja, o nome do arquivo consiste no timestamp do arquivo ini.

Isso pode ser alcançado na linha de comando?

    
por Finn Poppinga 21.03.2017 / 16:01

2 respostas

1

Ele pode ser alcançado na linha de comando, mas um script que seria executado na linha de comando seria uma solução mais fácil (eu acho).

etapas básicas:

1 Obtenha uma lista de diretórios para iterar     - find ${directory} -mindepth 1 -type d  2 Verifique cada diretório quanto à presença de um arquivo config.ini e um arquivo image.jpg.     - if [ -f ${subdir}/config.ini -a -f ${subdir}/image.jpg ]; then ...  3 Verifique o config.ini para todas as partes certas do timestamp.     - vários grep ^Year= ${subdir}/config.ini ou ^Month , etc ...  4 Faça uma cópia do arquivo image.jpg usando o timestamp.     - cp ${subdir}/image.jpg ${copydir}/${timestamp}.jpg

Acho mais fácil e potencialmente mais seguro colocar essas sequências em um script, onde você pode colocar mais facilmente resultados legíveis, tratamento de erros, etc.

Veja um script de exemplo para realizar essas etapas:

#!/bin/bash

imagepath="/path/to/images"
copydir="/path/to/copies"

# step 1: find all the directories
for dir in $(find ${imagepath} -mindepth 1 -type d); do
    echo "Procesing directory $dir:"
    ci=${dir}/config.ini
    jp=${dir}/image.jpg

    # step 2: check for config.ini and image.jpg
    if [ -f ${ci} -a -f ${jp} ]; then
        # step 3: get the parts of the timestamp
        year=$(grep ^Year= ${ci}   | cut -d= -f2)
        month=$(grep ^Month= ${ci} | cut -d= -f2)
        day=$(grep ^Day= ${ci}     | cut -d= -f2)
        hour=$(grep ^Hour= ${ci}   | cut -d= -f2)
        min=$(grep ^Minute= ${ci}  | cut -d= -f2)
        sec=$(grep ^Second= ${ci}  | cut -d= -f2)
        ms=$(grep ^Milliseconds= ${ci} | cut -d= -f2)

        # if any timestamp part is empty, don't copy the file
        # instead, write a note, and we can check it manually
        if [[ -z ${year} || -z ${month} || -z ${day} || -z ${hour} || -z ${min} || -z ${sec} || -z ${ms} ]]; then
            echo "Date variables not as expected in ${ci}!"
        else
            # step 4: copy file
            # if we got here, all the files are there, and the config.ini
            # had all the timestamp parts.
            tsfile="${year}-${month}-${day}T${hour}:${min}:${sec}:${ms}.jpg"
            target="${copydir}/${tsfile}"
            echo -n "Archiving ${jp} to ${target}: "
            st=$(cp ${jp} ${target} 2>&1)
            # capture the status and alert if there's an error
            if (( $? == 0 )); then
                echo "[ ok ]"
            else
                echo "[ err ]"
            fi
            [ ! -z $st ] && echo $st
        fi
    else
        # other side of step2... some file is missing... 
        # manual check recommended, no action taken
        echo "No config.ini or image.jpeg in ${dir}!"
    fi
    echo "---------------------"
done

É sempre bom ser um pouco conservador com scripts como esse, para que você não apague arquivos acidentalmente. Esse script faz apenas 1 ação de cópia, de modo que é bastante conservador e não deve prejudicar seus arquivos de origem. Mas você pode querer alterar ações específicas ou enviar mensagens para melhor atender às suas necessidades.

    
por 21.03.2017 / 17:09
0
top="$(pwd -P)" \
find . -type d -exec sh -c '
   shift "$1"
   for iDir
   do
      cd "$iDir" && \
      if [ -f "image.jpg" ] && [ -s "config.ini" ]; then
         eval "$(sed -e "/^[[]Acquisition]/,/^Milliseconds/!d
                  /^Year=/b; /^Month=/b; /^Day=/b; /^Hour=/b; /^Minute=/b
                  /^Second=/b; /^Milliseconds=/b; d" config.ini)"
         new=$(printf "%04d-%02d-%02dT%02d:%02d:%02d:%03d\n" \
                  "$Year" "$Month" "$Day" "$Hour" "$Minute" "$Second" "$Milliseconds")
         echo cp -p "image.jpg" "$new"
         cp -p "image.jpg" "$new"
      else
        #echo >&2 "$iDir/image.jpg &/or config.ini file(s) missing or empty."
        :
      fi
      cd "$top"
   done
' 2 1 {} +

#meth-2
find . -type f -name config.ini -exec perl -F= -lane '
    push @A, $F[1] if /^\[Acquisition]/ .. /^Milliseconds/ and
                     /^(?:Year|Month|Day|Hour|Minute|Second|Milliseconds)=/;
    next if ! eof;
    my(@a, $fmt) = qw/-  -  T  :  :  :/;
    (my $d = $ARGV) =~ s|/[^/]+$||;
    print( STDERR "No image.jpg in dir: $d"),next if ! -f $d . "/image.jpg";
    $fmt .= "${_}$a[$a++]" for map { "%0${_}s" } qw/4 2 2 2 2 2 3/;
    print for map { "$d/$_" } "image.jpg", sprintf "$fmt.jpg", @A;
    ($a,@A)=(0);
' {} + | xargs -n 2 echo mv
    
por 21.03.2017 / 20:37