Vai al contenuto

Aiuto espressioni regolari in *nix


jeby

Messaggi Raccomandati:

Ciao, avvicinandosi le vacanze si avvicina anche l'occasione di fare pulizia in archivi di file decennali.

Ho bisogno che qualcuno "mi impari" le espressioni regolari in bash per fare le cose bene e velocemente.

Problema:

Ho una serie di file che si chiamano ad esempio:

Vacanze Calabria 001_%2820030810%29_testo_vario

Vacanze Calabria 002_%2820030810%29_testo_vario

.

.

.

Vacanze Calabria 015_%2820030810%29_testo_vario

Vacanze Natale 001_%2820031225%29_testo_vario

.

.

.

Vacanze Natale 101_%2820031227%29_testo_vario

Berlino 001_%2820130520%29_testo_vario

.

.

.

Berlino 001_%2820130520%29_testo_vario

Ovviamente ci sono decine e decine di "tipologie" di nomi diversi ma tutti seguono lo stesso schema.

Quello che vorrei fare è sostituire tutti i "_" con " " e tutti i "%28" e "%29" con "(" e ")"

Per questa parte so che è possibile usare il comando sed in bash e non dovrebbe esser troppi difficile.

Fatto ciò vorrei che ogni file che comincia con "Vacanze Natale" vada a finire in una cartella che si chiama "Vacanze Natale", ovvero vorrei estrarre dal nome del file tutta la parte che sta prima dello spazio prima del primo numero. Così ad occhio mi sembra fattibile con espressioni regolari ma non ho idea di come fare!

Qualcuno sa come aiutarmi?

Grazie

Mazda MX-5 20th anniversary "barbone edition" - Tutto quello che scrivo è IMHO

k21x8z.png

Link al commento
Condividi su altri Social

  • Risposte 37
  • Creato
  • Ultima Risposta

I più attivi nella discussione

Giorni di maggior attività

I più attivi nella discussione

Ciao, avvicinandosi le vacanze si avvicina anche l'occasione di fare pulizia in archivi di file decennali.

Ho bisogno che qualcuno "mi impari" le espressioni regolari in bash per fare le cose bene e velocemente.

Problema:

Ho una serie di file che si chiamano ad esempio:

Vacanze Calabria 001_%2820030810%29_testo_vario

Vacanze Calabria 002_%2820030810%29_testo_vario

.

.

.

Vacanze Calabria 015_%2820030810%29_testo_vario

Vacanze Natale 001_%2820031225%29_testo_vario

.

.

.

Vacanze Natale 101_%2820031227%29_testo_vario

Berlino 001_%2820130520%29_testo_vario

.

.

.

Berlino 001_%2820130520%29_testo_vario

Ovviamente ci sono decine e decine di "tipologie" di nomi diversi ma tutti seguono lo stesso schema.

Quello che vorrei fare è sostituire tutti i "_" con " " e tutti i "%28" e "%29" con "(" e ")"

Per questa parte so che è possibile usare il comando sed in bash e non dovrebbe esser troppi difficile.

Fatto ciò vorrei che ogni file che comincia con "Vacanze Natale" vada a finire in una cartella che si chiama "Vacanze Natale", ovvero vorrei estrarre dal nome del file tutta la parte che sta prima dello spazio prima del primo numero. Così ad occhio mi sembra fattibile con espressioni regolari ma non ho idea di come fare!

Qualcuno sa come aiutarmi?

Grazie

Questa è una delle varie possibilità che ho buttato giù in questo momento:


#!/bin/bash

dir=`ls -l | grep '^d' | awk -v N=9 '{sep=""; for (i=N; i<=NF; i++) {printf("%s%s",sep,$i); sep=OFS}; printf("\n")}'`

while read -r folder;
do
if [[ $folder =~ (_|%28|%29) ]];
then
newfolder=$(echo $folder | sed 's/\_/\ /g')
newfolder=$(echo $newfolder | sed 's/%28/\(/g')
newfolder=$(echo $newfolder | sed 's/%29/\)/g')
echo "Renaming directory $folder in $newfolder"
mv "$folder" "$newfolder"
fi

done <<< "$dir"

l'ls con l'awk fa su un certo delirio per tirare fuori la lista di directory, divise per newline, che non dipendano dagli spazi (visto che ci sono) ne da altri caratteri speciali, di tutte le directory del path corrente, e poi, sed, a cascata applica la sostituzione di _, %28 e %29, dopodichè la directory viene rinominata con il nuovo nome.

Non è elegantissimo, ma dovrebbe essere abbastanza funzionale perchè non si preoccupa di matchare il nome delle directory (hai detto che ci sono molti nomi di directory diversi ma che contengono sempre questi caratteri), ma semplicemente di sostituire i caratteri incriminati.

Non dovrebbe avere effetto sulle directory che non matchano, visto che prima controlla con l'if.

Fammi sapere se ti gira.

Modificato da Artemis

"Fico, io ti rispondo che al buio tutti i gatti sembrano leopardi e che non bisogna mai comprare un gatto in un sacco. C'entrano qualcosa? Probabilmente no, esattamente come la tua metafora." [Loric]

Link al commento
Condividi su altri Social

copy running-config startup-config

copy startup-config flash:backupconfig

non c'entra nulla...ma mi sentivo sminuito nel mio essere informatico e non averci capito una fava :(((

i'm the Doctor, but beyond that, I.. I just don't know. I literally do not know who I am. It's all untested. Am I funny? Am I sarcastic? Sexy? Right old misery? Life and soul? Right-handed? Left-handed? A gambler? A fighter? A coward? A traitor or a liar? A nervous wreck? I mean, judging by the evidence, I've certainly got a gob.

Link al commento
Condividi su altri Social

intanto: grazie!

dir=`ls -l | grep '^d' | awk -v N=9 '{sep=""; for (i=N; i<=NF; i++) {printf("%s%s",sep,$i); sep=OFS}; printf("\n")}'`

questo genera una lista di cartelle senza simboli speciali (però perché N=9?)

tutto quello che sta nel ciclo while serve a sostituire i caratteri "_" e "%28" e "%29"

però io parto da una lista di file (per lo più jpg) e non di cartelle con quei nomi lunghissimi e voglio rinominare le cartelle solo con la prima parte del nome del file, ovvero la parte prima del 001, e poi muoverci dentro i file... se non ho capito male, manca questa parte, giusto?

Mazda MX-5 20th anniversary "barbone edition" - Tutto quello che scrivo è IMHO

k21x8z.png

Link al commento
Condividi su altri Social

intanto: grazie!

dir=`ls -l | grep '^d' | awk -v N=9 '{sep=""; for (i=N; i<=NF; i++) {printf("%s%s",sep,$i); sep=OFS}; printf("\n")}'`

questo genera una lista di cartelle senza simboli speciali (però perché N=9?)

tutto quello che sta nel ciclo while serve a sostituire i caratteri "_" e "%28" e "%29"

però io parto da una lista di file (per lo più jpg) e non di cartelle con quei nomi lunghissimi e voglio rinominare le cartelle solo con la prima parte del nome del file, ovvero la parte prima del 001, e poi muoverci dentro i file... se non ho capito male, manca questa parte, giusto?

N=9 perchè nell'ls -l il nome della directory inizia alla nona colonna. (almeno sul mio computer).

Per il resto della specifica, non ho capito prima e continuo a non capire ora. :D

I nomi che hai riportato nel primo messaggio sono nomi di file o di directory? Visto il nome io avevo dato per scontato che fossero directory, perchè solitamente è un po' pointless includere il soggetto dello scatto nel nome della foto stessa, visto che ci sono sempre più foto per lo stesso soggetto. :D

Comunque, fammi sapere se ho capito. Tu vuoi:


* Scorro i FILE
* Per ogni FILE:
* SE ci sono caratteri sfigati li sostituisco
* Controllo che esista una directory che ha come nome la parte del file che matcha ^(.*)\d{3} (quindi dall'inizio del nome a 001, 002, 003, ecc)
* SE la directory non esiste, creo la directory
* Muovo il file nella directory

E' esatto? :D

"Fico, io ti rispondo che al buio tutti i gatti sembrano leopardi e che non bisogna mai comprare un gatto in un sacco. C'entrano qualcosa? Probabilmente no, esattamente come la tua metafora." [Loric]

Link al commento
Condividi su altri Social

Mi fate venire in mente i bei tempi della tesi ( ma io lavoravo in korn shell :) )

Comunque riesco ancora a seguirlo..( a stento )

Forse io avrei fatto due ricorsive una per cambiar nome una per trasferire i file...ma non sono mai stato un gran programmatore :)

Archepensevoli spanciasentire Socing.

Link al commento
Condividi su altri Social


* Scorro i FILE
* Per ogni FILE:
* SE ci sono caratteri sfigati li sostituisco
* Controllo che esista una directory che ha come nome la parte del file che matcha ^(.*)\d{3} (quindi dall'inizio del nome a 001, 002, 003, ecc)
* SE la directory non esiste, creo la directory
* Muovo il file nella directory

E' esatto? :D

sì è esatto :birra: da "qualche testo 001 (eccetera) eccetera" a "qualche testo"

lo so che sono nomi di m....a ma si tratta di archivi di roba di più di dieci anni fa, batch di scatti da 300 foto fatti da chiunque passasse di lì con una compatta (gente che non so nemmeno più che fine abbia fatto), che hanno subito mille passaggi di sistemi di organizzazione e che per la maggior parte sono stati recuperati da un disco finito male... evviva! :D

Lo scopo è anche imparare sed o quel che è per fare altre operazioni su svariati altri file!

Modificato da jeby

Mazda MX-5 20th anniversary "barbone edition" - Tutto quello che scrivo è IMHO

k21x8z.png

Link al commento
Condividi su altri Social

sì è esatto :birra: da "qualche testo 001 (eccetera) eccetera" a "qualche testo"

lo so che sono nomi di m....a ma si tratta di archivi di roba di più di dieci anni fa, batch di scatti da 300 foto fatti da chiunque passasse di lì con una compatta (gente che non so nemmeno più che fine abbia fatto), che hanno subito mille passaggi di sistemi di organizzazione e che per la maggior parte sono stati recuperati da un disco finito male... evviva! :D

Lo scopo è anche imparare sed o quel che è per fare altre operazioni su svariati altri file!

Ho fatto una piccola aggiunta che dovrebbe fare tutto quello di cui hai bisogno:


#!/bin/bash

dir=`ls -l | grep '^-' | awk -v N=9 '{sep=""; for (i=N; i<=NF; i++) {printf("%s%s",sep,$i); sep=OFS}; printf("\n")}'`

while read -r file;
do
if [[ $file =~ (_|%28|%29) ]];
then
oldFile="$file"
file=$(echo $file | sed 's/\_/\ /g')
file=$(echo $file | sed 's/%28/\(/g')
file=$(echo $file | sed 's/%29/\)/g')
echo "** Renaming file $oldFile to $file"
mv "$oldFile" "$file"
fi
if [[ $file =~ ^([A-Za-z[:space:]]+)[0-9]{3}.*$ ]];
then
folder=`echo "${BASH_REMATCH[1]}" | awk '$1=$1'`
if [ ! -d "$folder" ];
then
mkdir "$folder"
echo "** Directory $folder created"
fi
echo "** Moving file $file to $folder"
mv "$file" "$folder"
fi

done <<< "$dir"

Mi sa che c'è un bug, ovvero che quando crea il nome della directory non toglie lo spazio in fondo e quindi crea la directory con il nome giusto ma con uno spazio in fondo.

C'è il modo di fare il trim dei leading spaces in bash, ma non mi ricordo a memoria come si fa e mi fa che non è proprio straightforward, quindi ho lasciato perdere. :D

Fammi sapere se funziona :D

Modificato da Artemis

"Fico, io ti rispondo che al buio tutti i gatti sembrano leopardi e che non bisogna mai comprare un gatto in un sacco. C'entrano qualcosa? Probabilmente no, esattamente come la tua metafora." [Loric]

Link al commento
Condividi su altri Social

Ho fatto una piccola aggiunta che dovrebbe fare tutto quello di cui hai bisogno:


#!/bin/bash

dir=`ls -l | grep '^-' | awk -v N=9 '{sep=""; for (i=N; i<=NF; i++) {printf("%s%s",sep,$i); sep=OFS}; printf("\n")}'`

while read -r file;
do
if [[ $file =~ (_|%28|%29) ]];
then
newfile=$(echo $file | sed 's/\_/\ /g')
newfile=$(echo $newfile | sed 's/%28/\(/g')
newfile=$(echo $newfile | sed 's/%29/\)/g')
echo "Renaming file $file to $newfile"
mv "$file" "$newfile"
fi
if [[ $file =~ ^([A-Za-z[:space:]]+)[0-9]{3}.*$ ]];
then
folder="${BASH_REMATCH[1]}"
if [ ! -d "$folder" ];
then
mkdir "$folder"
fi
mv "$newfile" "$folder"
fi

done <<< "$dir"

Mi sa che c'è un bug, ovvero che quando crea il nome della directory non toglie lo spazio in fondo e quindi crea la directory con il nome giusto ma con uno spazio in fondo.

C'è il modo di fare il trim dei leading spaces in bash, ma non mi ricordo a memoria come si fa e mi fa che non è proprio straightforward, quindi ho lasciato perdere. :D

Fammi sapere se funziona :D

Fantastico grazie!!!! Anche cono lo spazio in fondo va benissimo!

In pratica con BASH_REMATCH[1] vai a prendere solo la parte tra parentesi, giusto?

Appena riesco a far ripartire il cell provo che dal computer dell'ufficio non riesco a collegarmi con ssh a casa :)

Mazda MX-5 20th anniversary "barbone edition" - Tutto quello che scrivo è IMHO

k21x8z.png

Link al commento
Condividi su altri Social

Crea un account o accedi per lasciare un commento

Devi essere iscritto per commentare e visualizzare le sezioni protette!

Crea un account

Iscriviti nella nostra community. È facile!

Registra un nuovo account

Accedi

Sei già registrato? Accedi qui.

Accedi Ora

×
×
  • Crea Nuovo...

 

Stiamo sperimentando dei banner pubblicitari a minima invasività: fai una prova e poi facci sapere come va!

Per accedere al forum, disabilita l'AdBlock per questo sito e poi clicca su accetta: ci sarai di grande aiuto! Grazie!

Se non sai come si fa, puoi pensarci più avanti, cliccando su "ci penso" per continuare temporaneamente a navigare. Periodicamente ricomparità questo avviso come promemoria.