Visualizzazione post con etichetta script. Mostra tutti i post
Visualizzazione post con etichetta script. Mostra tutti i post

lunedì 19 gennaio 2015

Script cpMvBar

Da tempo ...
mi ritrovo ...
MALEDUCATO!!!
Ops ... ciao a tuttiii!!! :)

Di nuovo alle prese con una soluzione che ho voluto trovare, ad un problema ... pressoché inutile,
ma insomma che può almeno risparmiare un po' di stress quando si copiano file di notevoli dimensioni da terminale.

Non capita tutti i giorni sì (forse) ... ma proprio la scorsa settimana il mio capo e mi dice ...

Aldo non è possibile che non fai aggiornamenti del OS (windows) nella tua macchina virtuale!!!!
:OOOOO :( ...

Ehm ... sì li faccio ... ....
Mi tocca fare il backup de 59 gb de macchina virtuale?!!
Direi proprio che non ci sia altra scelta :/ ...
Chiaramente nautilus, bello figo ecc ... ma in termini di prestazioni e task aperti (almeno per la mia routine) non è che sia il massimo.
Come sempre c'è il nostro fido terminale, ma lo sappiamo che fare un cp/mv (copia / muovi .. :P ) da terminale di file grandi significa che bisogna ipotizzare quale sia la percentuale di progresso dell'operazione  copia/spostamento  ... :/ .

Qui ci vuole una barra di scorrimento per capire a che punto sta :) ! ...
Invece di affidarmi all'utility zenity come feci in passato che utilizza una gui grafica,
ho optato per uno script, chiaramente open source che permette di mostrare l'avanzamento della copia tramite una barra in caratteri ASCII ... il progetto, nello specifico lo potete trovare a questo indirizzo : http://www.theiling.de/projects/bar.html .

Non mi soffermo sul codice dello script, anche perché non è in bash e non essendo un mostro non ho le competenze per farlo, piuttosto mi soffermerò sulla sintassi della funzionalità principale.
Tale funzionalità si discosta un po'  dal cp in bash, e quindi ho preferito, realizzare uno script apposito per richiamarla.

Lo script non ha veramente niente di sofisticato, si tratta di gestire ... tramite un Case sul primo parametro passato (l'opzioni  -f, -F, -m e -M ) il tipo di operazione deve essere svolta.

Allo stato attuale, non utilizzo il richiamo alla funzione di copia directory, perché poco pratica (accennerò in breve il perché).

Comunque la barra che verrà mostrata in fase di copia sarà questa


Allora vediamo come copiare un file...
ah dimenticavo ... premetto che effettuo richiamo in modo diretto lo script "bar" ... perché spostato in /usr/bin
(ormai abitudine presa per tutti gli script fatti in casa e non che uso frequentemente).

sintassi :

bar -o $fileDestinazione $fileOrigine

Già si nota la prima differenza, la destinazione viene prima e il file di origine dopo.
Fin qui non sarebbe male, se non fossse che ... si deve specificare il file di destinazione e non la cartella, pertanto se si vuole spostare il file "lista.txt" nella cartella "liste" si dovrà eseguire così il comando:

bar -o liste/lista.txt lista.txt


Già questo, almeno per me, risulta un pò antipatico ...

Come dicevo, esiste anche l'opzione per la copia di una directory,
la sintassi

bar -c 'cat > cartella/${bar_file}' file1 file2 file3


(deduco che si sia capito, che lo script non fa altro che effettuare il cat delle operazioni)

Proprio per la copia di una directory devo lavorarci (tempo permettendo ... e solita poca pratica) ancora di più, per ora mi sono limitato a ciclare i soli files di una directory e copiarli uno per uno,
ma proprio perché sono cosciente essere una soluzione poco agevole e sicuramente da cambiare/migliorare, neanche la descrivo.

Allora iniziamo con la copia di un file, rendendo la copia più simile al cp classico.

Nel nostro script che come da titolo nominerò cpMvBar, gestirò diverse opzioni,
per la copia appunto sono due : "-f" e "-F" .

la sintassi nel primo caso sarà

cpMvBar -f $fileOrigine $fileDestinazione 

come si evince ... in realtà in questo caso non faccio assolutamente niente se non invertire l'ordine dei parametri, pertanto, il nome del file deve essere scritto anche nel secondo
Esempio:

cpMvBar -f lista.txt liste/lista.txt


la sintassi nel caso di parametro -F invece, sarà la seguente

cpMvBar -F $fileOrigine $cartellaDestinazione

questo è chiaramente come il comando cp (con in aggiunta l'opzione -F).

pertanto

cpMvBar -F lista.txt liste (nome directory senza il carattere slash finale "/")

per la copia ok.

Il comando bar, aimè non prevede lo spostamento, ma chiaramente ... se fossero questi i problemi :D ;) .

Come per la copia gestisco due casi con le opzioni -m e -M, anche in questo caso, nella prima opzione si deve specificare anche il nome del
file nella destinazione, mentre nel secondo no


cpMvBar -m lista.txt liste/lista.txt

cpMvBar -M lista.txt liste



in questi due ultimi casi non ho fatto altro che richiamare lo script bar, al solito modo, e aggiungere il classico rm successivamente.

Vi riporto di seguito l'intero script :


#! /bin/bash
#cpMvBar Script


while test -n "$1"
do
    case "$1" in
        -m)
              bar -o "$3" "$2"
             
rm "$2"
             
break
         ;;
         -M)

              bar -o "$3/$2" "$2"
             
rm "$2"
             
break
          ;;
          -f)
              bar
-o "$3" "$2"
             
break
           ;;
           -F)
              bar
-o "$3/$2" "$2"
             
break
           ;;
           -h) 

               echo 'Uso: copia [-f] [-d] [-h]'
               
echo 'Options:'
               
echo ' -h mostra questo help'
               echo ' -f copia il file'
               echo ' esempio copia -f fileOrigine fileDestinazione'
               echo ' -F copia il file'
               echo ' esempio copia -f fileOrigine cartellaDestinazione'
               echo ' -m sposta il file'
               echo ' esempio copia -m fileOrigine fileDestinazione'
               echo ' -M sposta il file'
               echo ' esempio copia -m fileOrigine cartellaDestinazione'
               break
             ;;
             *)
               echo
"opzione non gestita"
               break
             ;;
        esac

done



Una volta salvato come cpMvBar (o il nome che volete ... potete anche non omettere l'estensione .sh, ma in tal caso dovrete richiamarlo includendola)

una volta salvato in una directory a piacimento rendiamolo eseguibile con

chmod +x cpMvBar

se lo vogliamo lasciare in questa directory per eseguirlo occorre digitare
./cpMvBar ....

altrimenti possiamo, come nel mio caso aggiungerlo agli script eseguibili di ubuntu su /usr/bin

sudo cp cpMvBar /usr/bin

Chiaro? No? ...
Ah no ... se avrete già curiosato nel link dello script, noterete in realtà che bar non è un semplice script copia incolla, ma contiene, diverse funzionalità tutte da scoprire tra cui per esempio, menziono la barra di scorrimento in fase di compressione/decompressione file...

Questo è quanto ... (appunto il capo me chiama :/)
c.you soon



giovedì 16 gennaio 2014

Script MangaPdfConverter

Ciao a tutti!
Eh sì ... sto un po' trascurando il blog (alla faccia di un po' :P), logicamente gli impegni lavorativi, sentimentali e hobbistici ( :) ) annullano il tempo libero a disposizione.
Mi ritrovo a voler scrivere un nuovo post grazie ad una delle mie fonti di ispirazione preferite in ambito linux ... @bit3lux ed in particolare da un suo post sul suo blog che vi consiglio sentitamente (http://parliamodi-ubuntu.blogspot.it/2014/01/lo-script-radiosh-si-aggiorna.html).

Proprio nello script di cui parla l'articolo, mi si è aperto un piccolo mondo che per la mia limitata esperienza non avevo ancora esplorato, parlo dell'utility Zenity di cui senza super approfondire vi rimando al sito https://help.gnome.org/users/zenity/stable/index.html.en.

Per farla breve si tratta di un'applicazione che, da riga di comando, permette di utilizzare dialog in gtk, piuttosto utili.

La curiosità e la voglia di utilizzarla mi ha spinto a modificare un mio script di qualche settimana fa così da poter dar modo di impostare con un'interfaccia grafica, i parametri principali.

Come da titolo, lo script in questione, l'ho scritto per ottimizzare la mia collezione di manga giapponesi facendo sì che, grazie all'integrazione con un'altra applicazione, ogni volume, composto da tanti file .jpg/.png quante sono le pagine che lo compongono, venga convertito in pdf.
Questo può essere inoltre utile, anche quando si hanno a disposizione le scansioni di pagine di libri suddivisi in capitoli e le si vogliono unire in pdf...

Requisiti collezione (file system)

La struttura su file system della mia collezione è così disposta


  • Directory Manga1
    • Directory 001 (Cap 1)
    • Directory 002 (Cap 2)
    • ...
  • Directory Manga2
    • Directory 001 (Cap 1)
    • ...
  • Directory Manga3
    • ...
  • ...
In pratica ci sono tante directory quanti sono i manga che possiedo, ogni directory è composta da tante sottodirectory quanti sono i capitoli (ma volendo anche i volumi) del manga, ogni sottodirectory contiene tanti file .jpg/.png quante sono le pagine che compongono i capitoli.

Come test faccio l'esempio dell'ipotetico manga ArtigliDellaLince il manga è composto da 65 capitoli con un numero diverso di pagine.
Importante è precisare che, anche se, poi vedremo nello script, è parametrizzabile, in questa versione è necessario che all'interno di ogni directory-capitolo sia presente una pagina denominata 000 (che sia .jpg o .png è indifferente) che poi può fungere anche la cover del capitolo.
Di seguito grosso un idea della struttura

Lista directory contenute nel manga

Lista pagine

Il risultato della conversione saranno 65 file .pdf composti da tante pagine quanti sono i file all'interno delle directory "volumi".
I file saranno denominati
[NumeroVolume] [NomeManga].pdf
nel mio caso "001 ArtigliDellaLince.pdf", "002 ArtigliDellaLince.pdf" ecc...

Requisiti software

Cosa occorre per poter eseguire lo script ?
Innanzitutto, l'applicazione che fa il vero lavoro, ovvero ImageMagick ( http://www.imagemagick.org/).
E poi come detto prima zenity, ma questa dovrebbe essere già presente su Ubuntu (almeno nel mio caso ... acc... dimenticavo ... ora sto col pangolino ... Ubuntu 13.04 :P ).

Modus operandi

Come detto ImageMagick è il cuore dello script.
In pratica lo script, una volta impostata la cartella del manga, il nome ed il numero di capitoli, non farà altro che eseguire la riga di comando (per ogni directory) :

convert *.* "../$dir $manga.pdf" 

in parole spicce.. il comando convert, converte tutte le immagini contenute nella directory impostata su $dir nel pdf $dir $manga.pdf (dove $manga è appunto il nome del manga).


Piccola parentesi

Come detto precedentemente lo script è di qualche settimana fa, all'inizio non vi era implementazione con zenity pertanto i parametri [Manga], [Volumi] e [PercorsoDirectory] venivano impostati direttamente passandoli allo script da shell.


Richiamo script

Prima di descrivere il codice, vi stuzzico (:P) mostrandovi come lavora.
In ordine 

  • Salviamo lo script in una directory (io metto tutti gli script nella directory scripts nella mia home)
  • Rendiamolo eseguibile con il solito chmod +x MangaPdfConverter.sh
  • Eseguiamolo con ./MangaPdfConverter.sh 

 Per prima cosa ci verrà chiesto di impostare il nome del manga ed il numero di capitoli da cui è composto (trucco.. non è necessario che siano presenti tutte le directory da 1 a n l'importante è che n corrisponda al numero che impostiamo, verranno convertite solo le directory presenti).
Il dialog sarà il seguente :

Subito dopo aver premuto Ok, si aprirà il dialog che permetterà di selezionare, sfogliando il proprio file system, la directory del manga (quella appunto contenente le n directory dei capitoli)

Appena si conferma, avrà inizio la conversione

Al termine verrà mostrato (se tutto è andato ok) il seguente messaggio

Il risultato della conversione è la generazione di 65 file .pdf :

Code 

Descriviamo ora il codice.
La prima operazione svolta all'interno dello script è il settaggio di titolo e numero capitoli con il dialog mostrato sopra, questo è possibile tramite questo codice

datiManga=$(zenity --forms --title="Dati Manga" \
--text="Inserisci dettagli." \
--separator="|" \
--add-entry="Titolo" \
--add-entry="Numero Capitoli")

Nella variabile $datiManga verrà memorizzata una stringa tipo Titolo|NumeroCapitoli
che come si può capire sarà necessario splittare in due variabili ...

Ammetto, questa operazione che in Java risulta piuttosto semplice, su shell mi ci sono volute un pochino di ricerche soprattutto per capire cosa fosse la variabile IFS (rimando http://en.wikipedia.org/wiki/Internal_field_separator) e cosa servisse, pertanto dopo aver impostato il carattere pipe "|" come delimitatore scorro l'array generato dalla stringa e imposto la variabile $manga con Titolo e la variabile $numeri con i numeri dei capitoli.


#variabili iniziali
ix=0
OIFS=$IFS
IFS='|'
arr=$datiManga
numeri=0
manga=""

#imposto il titolo del manga e il numero dei capitoli ricavati 
#dal form (variabile $datiManga>$arr)
for cnt in $arr
do
case $ix in
0) manga="$cnt" ;;
1) numeri=$cnt ;;
esac
ix=$(( $ix + 1 ))
done

IFS=$OIFS

Dopo aver verificato con due banali if che la variabile $manga non è vuota e la variabile $numeri è diversa da zero imposto la variabile $path sempre grazie a zenity:

path=$(zenity --file-selection --directory)

Questo permetterà appunto l'apertura del dialog per sfogliare il file system e quindi selezionare la directory.

A questo punto non rimane altro che gestire il ciclo che per ogni directory eseguirà la conversione ...
se ... te pare facile :D ;)
Scherzo è facile ma proprio per interagire con zenity (per capirci con il dialog che mostra la progressbar con lo stato della conversione) ritengo necessario iniziare a descrivere il codice per gradi ...
( ... Codice ...) | zenity --progress \
 --title="Conversione Manga $manga" \
 --text="Cerco" \
 --percentage=0 \
 --width=500 \
 --auto-close
Per richiamare la progressbar di zenity, bisgogna seguire questa sintassi, ovvero,
mettere prima del suo richiamo, il codice che deve man mano impostare l'avanzamento di stato.

Chiaramente, il nostro codice imposterà di volta in volta il numero di capitolo e verificherà la presenza dei file 000.[estensione] (si lo so ... ma na verifica sulla presenza della directory non era meglio...? :/ :D )

Per aggiornare l'avanzamento  utilizzo una variabile $perc che per ogni item (inteso come numero capitolo) imposto, appunto la percentuale con un banale:
perc=`expr $x \* 100 / $numeri`

Praticamente richiamando
echo "$perc" 
si dirà a zenity quale la percentuale di avanzamento deve impostare sulla barra,
mentre richiamando
echo "# testo informativo" 
si dirà a zenity di mostrare il testo scelto come "stato" (la differenza è propio "#" all'inizio).

Il ciclo while che viene eseguito, parte dal valore iniziale 1 (valore di $x) al valore di $numeri e svolge le seguenti operazioni :
Imposta il valore della variabile $dir impostando qualora $x sia minore di 10 in "00$x" e qualora minore di 100 in "0$x"
if [ $x -lt 10 ]
then
     dir="00$x"
else
    if [ $x -lt 100 ]
    then
        dir="0$x"
    else
        dir="$x"
    fi
fi

In seguito, essendo ora a conoscenza del path e del nome della directory, verifico la presenza del file 000.[estensione].
Nel mio caso mi sono limitato a file con estensione .jpg, .png e .JPG, volendo se ne possono gestire anche altri tipo .gif ecc... l'unica cosa che ho verificato è che ImageMagick con alcuni tipi di .gif va in errore (immagino per codifiche diverse dal classico RGB, 8bit ecc), pertanto se possibile è bene verificare presenza di tali tipi di file.

Se la verifica ha effetto positivo imposto
la directory in cui mi devo spostare
toElab="$path/$dir"
e la variabile flag che mi consentirà di saltare la conversione se =  1
flg=0

Infine se $flg = 0
mi sposto nella directory
cd "$toElab"
aggiorno lo stato del dialog della progress di zenity
echo "# converto capitolo $dir"
unisco e converto tutte le immagini nel pdf
convert *.* "../$dir $manga.pdf"

Dall'istruzione
(.. codice ..) | zenity --progress ....
si ottiene un parametro di ritorno, che se  uguale -1 identifica la presenza di un errore durante l'esecuzione, se uguale a 0 significa che il codice è stato eseguito completamente e se uguale a 1 significa che il codice è stato interrotto anticipatamente (magari stoppato dall'utente)
pertanto il nostro dialog di conferma riporterà messaggi differenti in tutti e tre i casi :

if [ "$?" = -1 ] ; then
    zenity --error \
    --text="Conversione Fallita."
else
    if [ "$?" = 0 ] 
    then
        zenity --info --title="Success" \
        --text="Manga convertito correttamente!"
    else
        zenity --info --title="Success" \
        --text="Operazione terminata ! \n Non tutti i capitoli sono stati convertiti"
    fi
fi

Bè direi che con questo siamo arrivati alla fine... (e che ve pensavate fosse un poema?! :D) ...

Link Script completo (aimè dall'ufficio pastebin è bloccato :P ) : http://notepad.cc/share/w6GfeZvPjs

Critiche e autocritiche

Chi mi conosce sa che sviluppo in .net ma adoro il mondo linux, pertanto ammetto di aver scritto lo script utilizzando sintassi meno avanzata e non gestendo le 10.000 casistiche possibili nell'esecuzione,
ma spero da qui al prossimo futuro di implementare migliorie e nuove feature man mano che la mia conoscenza si consolida :) ... per ora posso solo dire che in casi come questo lo script da un bella mano, soprattutto se si è soliti leggere manga su dispositivi android come me, e quindi si preferisce invece di incasinare la propria galleria con migliaia di immagini, poter organizzarla in modo più ordinato utilizzando invece i pdf :) ...
Chiaramente le migliorie sono pronto ad implementarle grazie anche ai vostri consigli, sempre ben accetti ;)
ciao a tutti

venerdì 29 aprile 2011

Script ListDocSaver.py (facciamo un pò di ordine ... o quasi)


Ciao a tutti, sì sono stato maleducato nel post precedente a
non scusarmi...
Quindi chiedo scusa a tutti i lettori, per l'assenza prolungata dei mesi scorsi,
chiaramente causata da un periodo lavorativo molto impegnativo che di fatto mi ha portato via tempo e forze
per tener aggiornato il blog... bla bla bla..

Vorrei per farmi perdonare, un piccolo script che ho fatto per far pratica con Python che potrebbe interessare a qualcuno :) ..

Piccola premessa .... occorre una versione precedente alla 3.0...
Negli ultimi anni io, ma come tanti altri ho caricato il pc (vecchio e nuovo),  hard disk, pennette... cd e dvd di software, musica, video, documenti ecc...

Il problema è che a distanza di tempo ci si ritrova a porsi una domanda tipo :
cavolo mo' su quale Dvd ho salvato la canzone "Whole Lotta Love" dei Led Zeppelin?

GRRRR !!! Eh... appunto :

Trovare una canzone che non si ascolta da tempo, un video, un programma ecc...
su dvd/cd/HD ecc .. può diventare stressante...
Un pò di meno, se si elenchi per esempio, il contenuto di un Dvd masterizzato in precedenza su un file di testo.

Un semplicissimo file di testo dove, il più semplice Ctrl+F può diventare prezioso.

Per permettere allo script di accettare argomenti, si utilizza il modulo sys, opportunamente passato al metodo main (alla fine dello script):



Per rendere possibile la lettura degli argomenti  si deve importare il modulo getopt, con cui è appunto possibile stabilire il comportamento dello script in base al/ai parametri passati.

In questo script mi limito a gestire un solo parametro (-p e la sua versione estesa --path) e in alternativa i parametri -h (help) e -d (debug).

Senza dilungarmi troppo, provo a prendere i parametri, se qualcosa va storto mostro __doc__ (l'help), altrimenti passo al metodo popolaFileLog il valore del di -p
il risultato è il seguente :


Vengo infine al metodo popolaFileLog a cui appunto viene passato il percorso della directory (o dell'unità).
Piccola premessuccia, all'inizio dello script imposto la directory dove voglio salvare i file di testo creati, qui chiaramente ognuno dovrà impostare la directory scelta. ad esempio :
defaultPath='/home/nomeutente/Documenti/DVD-CD/'

Come lavora il metodo popolaFileLog..
Crea innanzitutto una lista in base al percorso passato... splittando il percorso con il carattere '/'
chiaramente a me interessa solamente il nome della directory e/o il nome dell'unità che per chi non lo sapesse su ubuntu solitamente viene mappata sotto /media/nomeUnita.

Poniamo ad esempio che ho passato allo script il percorso /media/mp3110428001 (dove mp3110428001 è l'etichetta assegnata al dvd/cd in fase di masterizzazione),
la lista ottenuta con il il metodo split sarà in questo caso
 ['', 'media', 'mp3110428001']
come detto mi interessa in questo caso mp3110428001, ma non sapendo (almeno quando si tratta di path di subdirectory) quanti elementi possa avere la lista ...
la inverto con il metoro reverse() che mi permetterà di avere il valore che mi interessa con lista[0] :


quindi compongo il path completo del file che andrò a creare che sarà così composto :


io ho usato la dicitura 'Contenuto'... ma ci si può mettere ciò che si vuole nel nostro caso il valore di pathFile sarà :

/home/nomeutente/Documenti/DVD-CD/Contenutomp3110428001.txt

a questo punto bisogna innanzitutto aprire il file in scrittura con

'w' sta per scrittura appunto :P

non ci rimane altro che sfogliare tutti i files, directory e subdirectory e scriverli nel file di testo ...
per memorizzare path, directory e files si utilizza il metodo walk del modulo os
e scorrere il tutto :

(nel mio caso ho lasciato anche subdirs per un eventuale uso ) chiaramente andando a capo ad ogni occorrenza trovata (con \n) ... chiaramente per ora non l'abbiamo nemmeno "toccato" il file... :)
per farlo bisogna "chiuderlo" con :
il metodo al completo sarà Richiamando quindi da riga di comando così : mi ritroverò nel file
/home/nomeutente/Documenti/DVD-CD/Contenutomp3110428001.txt dati tipo :
...
...
/media/MP3110428001/Led Zeppelin II/01 Whole Lotta Love.mp3
/media/MP3110428001/Led Zeppelin II/02 What is and What Should Never Be.mp3
/media/MP3110428001/Led Zeppelin II/03 The Lemon Song.mp3
/media/MP3110428001/Led Zeppelin II/04 Thank You.mp3
/media/MP3110428001/Led Zeppelin II/05 Heartbreaker.mp3
/media/MP3110428001/Led Zeppelin II/06 Living Loving Mad.mp3
/media/MP3110428001/Led Zeppelin II/07 Ramble On.mp3
/media/MP3110428001/Led Zeppelin II/08 Moby Dick.mp3
/media/MP3110428001/Led Zeppelin II/09 Bring It On Home.mp3
...
...
Cosicché la prossima volta potrò trovare, ad esempio la canzone che mi interessa più rapidamente...:)
per finire riporto il sorgente completo dello script ListDocSaver.py
Chiaramente, non nascondo che vorrei utilizzare questo script come base di partenza, magari per una classe di un futuro applicativo... magari pure con un qualche sorta di GUI grafica.. chissà! :D :D chiaramente attendo consigli e curiosità... che ho tanto da imparare :P