2010-08-30 14 views
5

Come un debuttante di script bash, le risposte dettagliate sarebbero apprezzate. :)Come analizzare i timestamp EXIF ​​con lo script Bash

Sto cercando di scrivere uno script bash che analizza JPEG EXIF ​​time stamp uscita dal programma di utilità exiv2 commmandline, che mi dà uscita tipici come:

Immagine timestamp: 2010: 07: 27 17: 38:52

C'è un modo per analizzare il timestamp in modo che i suoi componenti, come anno, mese, giorno, ora, minuto, secondo, passino alle rispettive variabili?

Sarebbe bello/gawk essere la strada da percorrere? Se é cosi, come? O è un altro modo migliore?

In questo modo, posso manipolarlo o combinarlo come preferisco.

Ecco lo script che ho finora:

#!/bin/bash 

COUNT=0 
SKIPPED=0 
FILES=0 # number of files encountered 

# declare variables for time stamp 

YEAR=0 
MONTH=0 
DAY=0 

HOUR=0 
MINUTE=0 
SECOND=0 

for CURRENT_FILE in * # a for loop to go through all files in current directory 
do 
    if [ -f "$CURRENT_FILE" ] # see if CURRENT_FILE is a file 
    then 
     FILETYPE=$(file -b --mime-type "$CURRENT_FILE") # get file type 
     if [[ $FILETYPE == image/jpeg ]] # see if CURRENT_FILE's mime is image/jpeg 
     then 
      ((COUNT++)) 
      echo "Processing file $COUNT: $CURRENT_FILE" 
      exiv2 "$CURRENT_FILE" | grep timestamp >> list 
     else 
      ((SKIPPED++)) 
      echo "Skipping file $CURRENT_FILE....." 
     fi 
     ((FILES++)) 
    fi 
done 

echo "Encountered $FILES files" 
echo "Processed $COUNT files" 
echo "Skipped $SKIPPED files" 

Grazie!

risposta

6

Ecco una soluzione bash pura per suddividere la linea specifica timestamp:

SPEC='Image timestamp : 2010:07:27 17:38:52' 
read X X YEAR MONTH DAY HOUR MINUTE SECOND <<<${SPEC//:/ } 
echo $YEAR 
echo $MONTH 
echo $DAY 
echo $HOUR 
echo $MINUTE 
echo $SECOND 

La soluzione sopra converte due punti per spazi nella specifica, divide su spazi, e pone ogni elemento nella rispettiva variabile.

Una soluzione che coinvolge awk, sed o Perl sarebbe simile, implementando la suddivisione in timestamp in una di quelle lingue.

Raccomando la soluzione di bash pura, perché è più veloce (non è necessario generare un sottoprocesso) e non ha dipendenze esterne. Oggigiorno (rispetto alla Bourne Shell degli anni '70) la maggior parte della manipolazione di stringhe e schiere può essere eseguita in bash, senza dover biforcarsi ed eseguire expr, tr, sed, awk, perl, tagliare ecc.

Con Perl :

SPEC='Image timestamp : 2010:07:27 17:38:52' 
read X X YEAR MONTH DAY HOUR MINUTE SECOND <<<$(perl -pe '[email protected]:@ @' <<<$SPEC) 
echo $YEAR 
echo $MONTH 
echo $DAY 
echo $HOUR 
echo $MINUTE 
echo $SECOND 

Con tr:

SPEC='Image timestamp : 2010:07:27 17:38:52' 
read X X YEAR MONTH DAY HOUR MINUTE SECOND <<<$(tr : ' ' <<<$SPEC) 
echo $YEAR 
echo $MONTH 
echo $DAY 
echo $HOUR 
echo $MINUTE 
echo $SECOND 

con sed:

SPEC='Image timestamp : 2010:07:27 17:38:52' 
read X X YEAR MONTH DAY HOUR MINUTE SECOND <<<$(sed 's/:/ /g' <<<$SPEC) 
echo $YEAR 
echo $MONTH 
echo $DAY 
echo $HOUR 
echo $MINUTE 
echo $SECOND 

con AWK:

SPEC='Image timestamp : 2010:07:27 17:38:52' 
read X X YEAR MONTH DAY HOUR MINUTE SECOND <<<$(awk '{gsub(/:/," ");print}' <<<$SPEC) 
echo $YEAR 
echo $MONTH 
echo $DAY 
echo $HOUR 
echo $MINUTE 
echo $SECOND 
+0

Questo è sorprendente. GRAZIE GRAZIE per la risposta rapida e molto dettagliata !!! :) – hpy

+0

Questa è davvero una grande risposta. – dawg

+1

Ecco una versione più semplice di 'split_timestamp':' split_timestamp() {local S = ($ {1 //: /}); echo $ {S [@]: 2}; } ' –

2

Ecco un altro modo

s="Image timestamp : 2010:07:27 17:38:52" 
$ IFS="[: ]" 
$ set -- $s 
$ echo $3 
2010 
$ echo $4 
07 
$ echo $5 
27 
$ echo $6 
17 
$ echo $7 
38 
$ echo $8 
52 
+0

Non è necessario [e] in IFS. Rendilo una funzione e rendi IFS una variabile locale. – pts