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.