martedì 31 marzo 2020

La potenza di linux


Ultimamente mi sono dilettato con un sistema Debian GNU/Linux.





Ho trovato molta difficoltà a riprendere in mano il linguaggio c, il mio obiettivo era creare uno script che presi tutti i files in una cartella, comprese tutte le sottocartelle, che finiscono solo per .part1.rar, .part01.rar .part001.rar .part0001.rar e .rar e li estragga ed eventualmente elimini i files estratti solo se l'estrazione vada a buon fine.





In C sarebbe un lavoraccio, ma alla fine mi sono detto: andiamo per gradi. Esiste il comando find.

il comando





find . -name '*.rar' -type f




elenca tutti i file nella directory corrente comprese le sottodirectory che finiscono in .rar.
E' un punto di partenza, ma se volessi trovare .part1.rar e .part01.rar dovrei fare altri due find.

Smanettando, ho trovato una espressione regolare, che vi mostro.





.part(0)*1.rar





Vuol dire la stringa deve iniziare per .part, dopo deve contenere un numero arbitrario di 0 e poi deve continuare con 1.rar.

find supporta le espressioni regolari? Certo che si.
Bisogna specificare i parametri -regextype per indicare il tipo di espressione regolare e poi -regex per indicare l'espressione regolare.
Quindi il comando diventa:





find .  -name '.rar' -type f -regextype egrep -regex '.part(0)*1.rar'




Ed elenca sia part01, che part1, che part001 e via discorrendo.

Il problema è che volendo fare uno script bash che spulcia la lista con un for, gli spazi rompono il comando, cioè "file 01.part01.rar" viene considerato come 2 file: file e 01.part01.rar

Come evitare ciò? Fortnatamente find supporta anche l'esecuzione di comandi arbitraria, col parametro -exec, il parametro {} indica la path assoluta del file in esame.

Per cui il comando diventa:





find . -name '.rar' -type f -regextype egrep -regex '.part(0)*1.rar'  -exec unrar x {} \;




Così spulcia tutti i file rar che finiscono con 1,01,001.rar e li estrae.





Adesso, per ottenere la path corrispondente la directory del file, bisogna usare il comando dirname, però non c'è modo di usarlo per bene all'interno di find, manco richiamando bash, e rm si rifiuta di eliminare la directory "." che sarebbe quella corrente.

In rete ho trovato qualcosa, non so esattamente cosa fa ma funziona, ed è:





-exec bash -c 'rm -rf "${@%/*}"' -- {}




richiama una shell interattiva e gli dice di rimuovere qualcosa, cosa lo ignoro.
Fortunatamente il find può accettare più parametri exec ed esegue il secondo solo se il primo va a buon fine, il terzo solo se il secondo va a buon fine e via discorrendo.

Per cui il comando diventa:





find ~/Scaricati/jdownloader/ -name '.rar' -type f -regextype egrep -regex '.part(0)1.rar'  -exec unrar x {} \; -exec bash -c 'rm -rf "${@%/}"' -- {}




E fino a qua ci siamo.

Questo comando trova tutti part1, part01, part001 rar e li estrae e se l'estrazione va a buon fine elimina la directory con all'interno tutti i file.

Ma non è ancora quello che volevo, perché il singolo file rar non viene considerato.

Ho trovato in rete una regex bestiale che funziona, e vi riporto:





.*(?:(?<!part\d\d\d|part\d\d|\d)\.rar|\.part0*1\.rar)|.*part(0)*1\.rar




Questa regex bestiale non so bene come funziona, ma la prima parte fa si che non ci sia nessun part0, e la seconda parte, dopo il | è quella che portato all'inizio.

Il problema è che find non è sufficientemente potente per elaborare questa regex, infatti ignora beatamente la prima parte.

Quindi prima si fa un find trovando i vari part0, si eliminano TUTTI i file, compresi i 02, 03 eccetera, e poi si fa un secondo find beccando tutti i rar singoli, senza specificare part e via discorrendo.

Ecco il mio scriptino bash che richiama il file da riga di comando unrar che estrae ed elimina tutti i rar, solo se l'estrazione è andata a buon fine, chiedendo a schemo una eventuale password.





!/bin/bash
find ~/Scaricati/jdownloader/ -name '.rar' -type f -regextype egrep -regex '.part(0)1.rar' -exec unrar x {} \; -exec bash -c 'rm -rf "${@%/}"' -- {}
find /var/lib/jdownloader/Downloads -name '.rar' -exec unrar x {} \; -exec bash -c 'rm -rf "${@%/}"' -- {}




Perl supporta la regex bestiale, per cui con l'interprete perl è possibile fare tutto con una sola riga di comando, solo che il perl proprio non lo conosco, per cui, per il momento, mi accontento di due semplicissimi comandi per estrarre i rar di jdownloader.

L'interpete perl è richiamabile al posto di bash, mentre in windows bisognerebbe fare un programma apposito.


Il backup di windows si è evoluto

  Adesso è legato a microsoft 365, che permette di avere 1 tb di spazio su onedrive. La lista delle app salvate è quella scaricata dal windo...