Ho già creato il medesimo articolo dedicato a Linux ma, essendo lo script che esegue l’operazione, piuttosto diverso nella versione iMac ho, per praticità, preferito crearlo ex-novo.
Il problema: cambiare la data ad un insieme di foto (ma, volendo, a qualsiasi file) con uno strumento sufficientemente potente, che mi consenta di stabilire se eseguire addizioni/sottrazioni alle date, piuttosto che impostare la data odierna o comunque una forzata.
So che, per iMac, esistono soluzioni a pagamento su AppStore che eseguono l’operazione ma: perché pagare per un’applicazione che sono capace di crearmi anche da solo ?
Mi rendo conto che, per gli utenti iMac, la soluzione proposta sia decisamente meno fruibile che non per quelli Linux, dal momento che sono meno avvezzi all’uso del terminale, tuttavia, mi permetto di proporla ugualmente per chi vuole comunque – e in tempi rapidi ed economici – una soluzione al problema di cui sopra, che si presenta piuttosto puntualmente nel momento in cui si vanno ad importare fotografie da una fotocamera digitale. La data sballata, soprattutto nel momento in cui si esegue l’importazione in iPhoto, è un problema fastidioso che va risolto prima, perché con quest’ultima applicazione non è altrettanto pratico ed efficace.
Come prima cosa dobbiamo creare lo script bash (sostanzialmente un programma interpretato run-time dal sistema Mac OS X) che esegue l’operazione; i passaggi sono i seguenti:
- Si apre un Terminale; dal Finder si va in Applicazioni -> Utility -> Terminale
- Si devono ottenere i privilegi di amministratore (in questo modo è possibile salvare lo script in una cartella di sistema, accessibile da qualsiasi utente); per farlo si digita il comando:
sudo bash
e si preme INVIO per eseguirlo (da ora in poi, premere sempre INVIO quando suggerisco l’esecuzione di un comando a terminale). Affinché il comando possa essere eseguito è necessario introdurre la password che si utilizza per fare login con l’utente attuale.
- Si rende corrente la cartella dove andremo a collocare lo script con il comando:
cd /usr/local/bin
e si apre la creazione dello script con questi 2 comandi:
vi uda_change_time i
- A questo punto bisogna fare un copia/incolla del seguente codice:
#!/bin/bash # Script per cambiare la data ai files specificati. # Versione iMac 2012.12.26.a # By UDA'Software 2012 ################################################################################ #_______________________________________________________________________________ function print_help() { printf 'Sintassi: %s [--help] <ora> <minuti> <secondi> <giorni> <mesi> <anni> [OPTIONS]\n' "${0}" cat<<EOF Scopo dello script e' quello di modificare la data e l'ora dei files specificati,aggiungendo o sottraendo "tempo". Il "tempo" viene specificato con 6 parametri, che possono essere positivi o negativi - aggiungendo il segno "-" (meno) -, rappresentati l'entità che si vuole andare, rispettivamente, ad aggiungere o togliere alla data corrente dei files che verranno elaborati. Ad esempio: ${0} 5 -30 20 4 -3 10 miafoto.jpg produce come effetto che alla data di creazione del file "miafoto.jpg" saranno aggiunte 5 ore, sottratti 30 minuti, aggiunti 20 secondi, aggiunti 4 giorni, sottratti 3 mesi e aggiunti 10 anni. Volendo elaborare piu' files contemporaneamente e' possibile utilizzare i caratteri jolly; ad esempio: ${0} 5 -30 20 4 -3 10 '*.jpg' OPZIONI E' possibile utilizzare delle opzioni che modificano il comportamento base dello script, ovvero: --test Modalita' di simulazione; non esegue nessuna modifica, aiuta solo a capire come la data dei files specificati verra' modificata. --ask Modalita' di richiesta; prima di procedere alla modifica dei files specificati, chiede conferma. Con la risposta "a" si ottiene l'interruzione definitiva. --current Ignora i parametri - relativi al tempo di modifica - e utilizza la data corrente per stabilire quella che dovranno assumere i files specificati. --force Anziche' utilizzare i parametri come modificatori della data corrente dei files da elaborare, vengono utilizzati per stabilirla esattamente; questo determina che il parametro "anni", anziche' essere trattato come la quantita' di anni da aggiungere o sottrarre, deve essere a 4 cifre e rappresentare direttamente l'anno che si intende configurare. EOF exit 0; } ################################################################################ #_______________________________________________________________________________ function calcola_max_giorni() { case ${file_mese} in 1) # Gennaio max_giorni=31 ;; 2) # Febbraio if (( (anno % 400) == 0 )) || (( (anno % 4) == 0 && (anno % 100) != 0 )); then max_giorni=29 else max_giorni=28 fi ;; 3) # Marzo max_giorni=31 ;; 4) # Aprile max_giorni=30 ;; 5) # Maggio max_giorni=31 ;; 6) # Giugno max_giorni=30 ;; 7) # Luglio max_giorni=31 ;; 8) # Agosto max_giorni=31 ;; 9) # Settembre max_giorni=30 ;; 10) # Ottobre max_giorni=31 ;; 11) # Novembre max_giorni=30 ;; 12) # Dicembre max_giorni=31 ;; esac } ################################################################################ #_______________________________________________________________________________ ora="${1:-0}" minuti="${2:-0}" secondi="${3:-0}" giorno="${4:-0}" mese="${5:-0}" anno="${6:-0}" files="${7}" if [ "${1}" == "--help" ]; then print_help fi if [ "${files}" == "" ]; then printf 'ERRORE: Non hai specificato i paramatri correttamente.\nUsare: %s --help\n' "${0}" exit 1; fi while [ "$8" != "" ]; do case ${8} in "--test") flag_test=1 printf '(Attivata la modalita simulazione)\n' ;; "--ask") flag_ask=1 printf '(Attivata la modalita richiesta di modifica)\n' ;; "--current") flag_current=1 printf '(Attivata la modalita data corrente)\n' ;; "--force") flag_force=1 if [ ${ora} -lt 0 ] || [ ${ora} -gt 23 ]; then printf 'ERRORE: Hai specificato una data non valida; l ora non deve essere inferiore a 0 e superiore a 23.\n' exit 1; fi if [ ${minuti} -lt 0 ] || [ ${minuti} -gt 59 ]; then printf 'ERRORE: Hai specificato una data non valida; i minuti non devono essere inferiori a 0 e superiori a 59.\n' exit 1; fi if [ ${secondi} -lt 0 ] || [ ${secondi} -gt 59 ]; then printf 'ERRORE: Hai specificato una data non valida; i secondi non devono essere inferiori a 0 e superiori a 59.\n' exit 1; fi if [ ${mese} -lt 1 ] || [ ${mese} -gt 12 ]; then printf 'ERRORE: Hai specificato una data non valida; i mesi non devono essere inferiori a 1 e superiori a 12.\n' exit 1; fi if [ ${anno} -lt 1970 ] || [ ${anno} -gt 9999 ]; then printf 'ERRORE: Hai specificato una data non valida; l anno non deve essere inferiore al 1970.\n' exit 1; fi file_mese=${mese} calcola_max_giorni if [ ${giorno} -lt 1 ] || [ ${giorno} -gt ${max_giorni} ]; then printf 'ERRORE: Hai specificato una data non valida; i giorni non devono essere inferiori a 1 e superiori a %d.\n' ${max_giorni} exit 1; fi printf '(Attivata la modalita data forzata [%02d:%02d:%02d %02d/%02d/%02d])\n' ${ora} ${minuti} ${secondi} ${giorno} ${mese} ${anno} ;; esac shift done ################################################################################ #_______________________________________________________________________________ if [ ${flag_current:-0} == 0 ] && [ ${flag_force:-0} == 0 ]; then if [ ${ora} -lt 0 ]; then printf '* All orario saranno sottratte %d ore\n' ${ora/-/} else printf '* All orario saranno aggiunte %d ore\n' ${ora/-/} fi if [ ${minuti} -lt 0 ]; then printf '* All orario saranno sottratte %d minuti\n' ${minuti/-/} else printf '* All orario saranno aggiunte %d minuti\n' ${minuti/-/} fi if [ ${secondi} -lt 0 ]; then printf '* All orario saranno sottratte %d secondi\n' ${secondi/-/} else printf '* All orario saranno aggiunte %d secondi\n' ${secondi/-/} fi if [ ${giorno} -lt 0 ]; then printf '* Alla data saranno sottratti %d giorni\n' ${giorno/-/} else printf '* Alla data saranno aggiunti %d giorni\n' ${giorno/-/} fi if [ ${mese} -lt 0 ]; then printf '* Alla data saranno sottratti %d mesi\n' ${mese/-/} else printf '* Alla data saranno aggiunti %d mesi\n' ${mese/-/} fi if [ ${anno} -lt 0 ]; then printf '* Alla data saranno sottratti %d anni\n' ${anno/-/} else printf '* Alla data saranno aggiunti %d anni\n' ${anno/-/} fi fi for file in ${files}; do if [ -f ${file} ]; then printf 'Elaborazione del file: %s\n' "${file}" file_timestamp=$(stat -f %m ${file}) file_ora=$(date -r ${file_timestamp} +%H | sed 's@^0@@') file_minuti=$(date -r ${file_timestamp} +%M | sed 's@^0@@') file_secondi=$(date -r ${file_timestamp} +%S | sed 's@^0@@') file_giorno=$(date -r ${file_timestamp} +%d | sed 's@^0@@') file_mese=$(date -r ${file_timestamp} +%m | sed 's@^0@@') file_anno=$(date -r ${file_timestamp} +%Y | sed 's@^0@@') printf ' Data corrente : %02d:%02d:%02d %02d/%02d/%04d\n' ${file_ora} ${file_minuti} ${file_secondi} ${file_giorno} ${file_mese} ${file_anno} if [ ${flag_current:-0} == 0 ]; then if [ ${flag_force:-0} == 0 ]; then delta_timestamp=$(($((${ora} * 3600)) + $((${minuti} * 60)) + ${secondi})) file_timestamp=$((${file_timestamp} + ${delta_timestamp})) file_ora=$(date -r ${file_timestamp} +%H | sed 's@^0@@') file_minuti=$(date -r ${file_timestamp} +%M | sed 's@^0@@') file_secondi=$(date -r ${file_timestamp} +%S | sed 's@^0@@') file_anno=$(($(date -r ${file_timestamp} +%Y | sed 's@^0@@') + ${anno})) file_mese=$(($(date -r ${file_timestamp} +%m | sed 's@^0@@') + ${mese})) if [ ${file_mese} -gt 12 ]; then file_mese=1 file_anno=$((${file_anno} + 1)) elif [ ${file_mese} -lt 1 ]; then file_mese=12 file_anno=$((${file_anno} - 1)) fi calcola_max_giorni file_giorno=$(($(date -r ${file_timestamp} +%d | sed 's@^0@@') + ${giorno})) if [ ${file_giorno} -gt ${max_giorni} ]; then file_giorno=1 file_mese=$((${file_mese} + 1)) if [ ${file_mese} -gt 12 ]; then file_mese=1 file_anno=$((${file_anno} + 1)) fi elif [ ${file_giorno} -lt 1 ]; then file_mese=$((${file_mese} - 1)) if [ ${file_mese} -lt 1 ]; then file_mese=12 file_anno=$((${file_anno} - 1)) fi calcola_max_giorni file_giorno=${max_giorni} fi else file_ora=$(echo "${ora}" | grep -o '[0-9]*' | sed 's@^00@0@g') file_minuti=$(echo "${minuti}" | grep -o '[0-9]*' | sed 's@^00@0@g') file_secondi=$(echo "${secondi}" | grep -o '[0-9]*' | sed 's@^00@0@g') file_giorno=$(echo "${giorno}" | grep -o '[0-9]*' | sed 's@^00@0@g') file_mese=$(echo "${mese}" | grep -o '[0-9]*' | sed 's@^00@0@g') file_anno=$(echo "${anno}" | grep -o '[0-9]*' | sed 's@^00@0@g') fi else file_ora=$(date +%H) file_minuti=$(date +%M) file_secondi=$(date +%S) file_giorno=$(date +%d) file_mese=$(date +%m) file_anno=$(date +%Y) fi if [ ${flag_test:-0} == 0 ]; then if [ ${flag_ask:-0} == 0 ]; then answer="S" else printf ' Data prevista : %02d:%02d:%02d %02d/%02d/%04d\n' ${file_ora} ${file_minuti} ${file_secondi} ${file_giorno} ${file_mese} ${file_anno} printf 'Vuoi modificare la data del file %s ? (S/n/a)\n' read answer if [ "${answer}" == "a" ] || [ "${answer}" == "A" ]; then printf '\nABORTITO !\n' exit 0; fi fi if [ "${answer}" != "n" ] && [ "${answer}" != "N" ]; then printf ' Data modificata : %02d:%02d:%02d %02d/%02d/%04d\n' ${file_ora} ${file_minuti} ${file_secondi} ${file_giorno} ${file_mese} ${file_anno} file_ora=$(printf '%02d\n' ${file_ora}) file_minuti=$(printf '%02d\n' ${file_minuti}) file_secondi=$(printf '%02d\n' ${file_secondi}) file_giorno=$(printf '%02d\n' ${file_giorno}) file_mese=$(printf '%02d\n' ${file_mese}) file_anno=$(printf '%04d\n' ${file_anno}) /usr/bin/SetFile -d "${file_mese}/${file_giorno}/${file_anno} ${file_ora}:${file_minuti}:${file_secondi}" "${file}" if [ ${?} != 0 ]; then printf 'ERRORE: Nel cambiare la data di creazione si e verificato un problema con codice %d \n' ${?} fi /usr/bin/SetFile -m "${file_mese}/${file_giorno}/${file_anno} ${file_ora}:${file_minuti}:${file_secondi}" "${file}" if [ ${?} != 0 ]; then printf 'ERRORE: Nel cambiare la data di modifica si e verificato un problema con codice %d \n' ${?} fi fi else printf ' Data prevista : %02d:%02d:%02d %02d/%02d/%04d\n' ${file_ora} ${file_minuti} ${file_secondi} ${file_giorno} ${file_mese} ${file_anno} fi else printf 'ERRORE: File %s non trovato !\n' "${file}" fi done ################################################################################ #_______________________________________________________________________________ - Ora dobbiamo salvare il codice incollato premendo il tasto ESC della tastiera e il comando:
ZZ
(facendo attenzione a rispettare le maiuscole)
- Bene, è arrivato il momento di rendere eseguibile lo script con il comando:
chmod +x uda_change_time
e uscire dallo stato di amministratore con il comando:
exit
Ok, fino a qui, sono le operazioni – da eseguirsi solo una volta – necessarie per creare lo script e renderlo eseguibile; adesso passiamo alla modifica dei file in oggetto !
Supponiamo di avere una SD-Card con le foto, la inseriamo nell’apposito slot, l’iMac monta la card e, sul desktop, ci mostra la relativa icona. Il nostro problema è ora, da terminale, rendere corrente la cartella contenente le foto o comunque i files – da sistemare.
N.B.: Quando si inserisce una SD-Card o comunque si collega una fotocamera, facile che iPhoto parta in automatico. Non è il momento opportuno per importare le foto, la data va sistemata prima, non dopo, quindi chiuderlo.
Utilizzare l’icona sul desktop per aprire la finestra nel Finder, navigare nelle cartelle presenti sul dispositivo al fine di trovare le foto da modificare; a questo punto, nel terminale, scrivere il comando (senza premere INVIO):
cd
(notare che, dopo “cd”, c’è uno spazio, rispettarlo !) e, dalla finestra del Finder dove sono presenti le foto, cliccare – nel titolo della finestra – sull’icona della cartella finale – antecedente il nome della stessa – e trascinarla nella finestra del Terminale e lì rilasciare. Si ottiene che Mac OS X copia in automatico, nel terminale, il percorso corretto, facendo in modo che il comando che si è precedentemente iniziato a scrivere diventi simile al seguente:
cd /Volumes/Untitled/DCIM/101SSCAM
Ecco, ora, si può premere INVIO. Per verificare che tutto sia stato eseguito correttamente, usare il comando:
ls
per elencare i files presenti; mi aspetto siano elencati dei file con estensione “.JPG”, tuttavia, i comandi che andrò a proporre di seguito servono per modificare qualsiasi file sia presente nella cartella corrente.
Ora è giunto il momento di passare alla modifica della data/ora. Sono presenti più metodi:
- Aggiungere o sottrarre del “tempo” alla data/ora corrente dei file.
- Impostare a tutti i file la data e l’ora corrente.
- Impostare a tutti i file la data e l’ora desiderate.
Notare che solo la prima soluzione – che è quella consigliata – consente di impostare la data e l’ora che i file dovevano avere già in origine, le altre due la forzano ad una ben precisa.
Il mio consiglio è quello di partire da un comando di test che non modifica nulla, ma consente di elencare i file con la loro data corrente, in modo da rendersi conto dell’entità di tempo da usare per la modifica. Il comando è il seguente:
uda_change_time 0 0 0 0 0 0 '*' --test
N.B.: Il Terminale di Mac OS X (ma quelli UNIX in generale) sono strumenti molto potenti; tra le varie cose è possibile ripristinare i comandi dati in precedenza usando i tasti freccia della tastiera. E’ anche possibile farsi aiutare nel completamento dei comandi da eseguire utilizzando il tasto “->|” (tabulazione); ad esempio, se si inizia a scrivere “uda” e si preme il tasto tabulazione , si ottiene che viene automaticamente scritto “uda_time_change”, risparmiando fatica e la possibilità di errori.
Nel comando dato in precedenza bisogna porre attenzione ai sei parametri numerici “0” (zero) che, rispettivamente, rappresentano: ora, minuti, secondi, giorni, mesi e anni di modifica.
Ad esempio, supponiamo che l’ora/data delle nostre foto sia sballata in maniera che, per ripristinarla, sia necessario: togliere 3 ore, aggiungere 10 minuti, togliere 30 secondi, togliere 6 giorni, aggiungere 2 mesi e aggiungere 4 anni.
Il comando che – ancora in fase di test – andremo a dare sarà il seguente:
uda_change_time -3 10 -30 -6 2 4 '*' --test
così da renderci conto se l’operazione avrà gli effetti desiderati; se ciò si verifica, possiamo procedere effettivamente alla modifica (togliendo l’opzione “–test”) con:
uda_change_time -3 10 -30 -6 2 4 '*'
Per una guida completa dello script, usare:
uda_change_time --help
Una volta terminata la modifica della data, possiamo uscire dal terminale con il comando:
exit
e la combinazione di tasti cmd+q .
Non ultimo: Non mi assumo nessuna responsabilità per qualsiasi danno possa eventualmente derivare direttamente o indirettamente da quanto descritto in questo articolo e dall’uso proprio o improprio dello script.