Repository 32bit  Forum
Repository 64bit  Wiki

Rendere uno script ricorsivo

Forum dedicato alla programmazione.

Moderatore: Staff

Regole del forum
1) Citare in modo preciso il linguaggio di programmazione usato.
2) Se possibile portare un esempio del risultato atteso.
3) Leggere attentamente le risposte ricevute.
4) Scrivere i messaggi con il colore di default, evitare altri colori.
5) Scrivere in Italiano o in Inglese, se possibile grammaticalmente corretto, evitate stili di scrittura poco chiari, quindi nessuna abbreviazione tipo telegramma o scrittura stile SMS o CHAT.
6) Appena registrati è consigliato presentarsi nel forum dedicato.

La non osservanza delle regole porta a provvedimenti di vari tipo da parte dello staff, in particolare la non osservanza della regola 5 porta alla cancellazione del post e alla segnalazione dell'utente. In caso di recidività l'utente rischia il ban temporaneo.

Rendere uno script ricorsivo

Messaggioda fortea » gio lug 15, 2010 13:19

Buon giorno a tutti. Sono nuovo del forum e piuttosto nuovo di Linux.

Mi chiedevo come si può rendere uno script (scritto da me) ricursivo nelle sottodierctory. Nel particolare, il mio comando sostituisce alcuni caratteri (ad esempio gli spazi) nei nomi dei file e delle directory presenti nella directory in cui ci si trova. Vorrei però che all'occorrenza funzionasse anche nei file e nelle directory presenti nelle sottodirectory.
Un'altra cosa: e per farlo funzionare in una directory o su un file espresso come argomento del comando?

Grazie per le risposte, copio il codice:

Codice: Seleziona tutto
#!/bin/sh
#controllo dei parametri passati dalla riga di comando
if [$1 = ]
   then
   echo -n 'Would you like to cancel spaces in all files of this directory? [y/n] '
   read answer_a
   str1="$answer_a"
   if [ $str1 = "y" ]
   then
      REPLACE_CHAR="\ "
   #eliminazione dei file i cui nomi contengono spazi
      for file in ls *
      do
         if [ "$file" = "ls" ]
         then
            str1="$file" #operazione inutile, non so dirgli di non fare nulla; qui non deve fare niente
         else
         str2=`echo $file | sed s/\ /_/g`  #il comando sed sostituisce nella stringa s il terzo parametro al posto del secondo
         if [ "$file" = $str2 ]
         then
         niente=$file
         #echo $file   #stampa i nomi dei files non modificati      
         else
         echo $file  ">>>>>>" $str2   #stampa i nomi dei files modificandi e modificati      
         mv "$file" $str2 #cambia il nome del file con quello contenuto in $str
         fi
         fi
      done

      REPLACE_CHAR="_-_"
   #eliminazione dei file i cui nomi contengono spazi
      for file in ls *
      do
         if [ "$file" = "ls" ]
         then
            str3="$file" #operazione inutile, non so dirgli di non fare nulla; qui non deve fare niente
         else
         str4=`echo $file | sed s/_-_/_/g`  #il comando sed sostituisce nella stringa s il terzo parametro al posto del secondo
         if [ "$file" = $str4 ]
         then
         niente=$file   #operazione inutile, ma qui non deve fare niente   
         else
         echo $file  "   >>>>>>   " $str4   #stampa i nomi dei files modificandi e modificati      
         mv "$file" $str4 #cambia il nome del file con quello contenuto in $str
         fi
         fi
      done





   exit
   

   fi
   exit
fi
exit
fortea
Linux 1.0
Linux 1.0
 
Messaggi: 24
Iscritto il: gio lug 15, 2010 13:00
Slackware: 13.0
Kernel: 2.6.29.6
Desktop: fluxbox

Re: Rendere uno script ricursivo

Messaggioda masalapianta » gio lug 15, 2010 14:30

sotituisci "ls *" (perchè metti "ls"? basta "*") con un find; btw fai prima così:
export OLDIFS=$IFS; export IFS=$'\n';for i in `find . -type f`; do mv "$i" "`echo $i|tr \" \" \"_\"`";done;IFS=$OLDIFS
ovviamente se vuoi rinominare anche le directory basta levare il -type f
Avatar utente
masalapianta
Iper Master
Iper Master
 
Messaggi: 2775
Iscritto il: dom lug 24, 2005 23:00
Località: Roma
Nome Cognome: famoso porco
Kernel: uname -r
Desktop: awesome
Distribuzione: Debian

Re: Rendere uno script ricursivo

Messaggioda anycolouryoulike » gio lug 15, 2010 14:36

Io farei così:
Codice: Seleziona tutto
IFS=$'\n'
for i in $(find . -type f -name "* *")
do
mv $i $(echo $i | tr ' ' '_')
done
Sono stato anticipato :)
Avatar utente
anycolouryoulike
Packager
Packager
 
Messaggi: 1158
Iscritto il: gio ago 09, 2007 23:00
Slackware: 12.2
Kernel: 2.6.34.8
Desktop: KDE 3.5.10

Re: Rendere uno script ricursivo

Messaggioda conraid » gio lug 15, 2010 14:39

anycolouryoulike ha scritto:Io farei così:
Codice: Seleziona tutto
IFS=$'\n'
for i in $(find . -type f -name "* *")
do
mv $i $(echo $i | tr ' ' '_')
done
Sono stato anticipato :)


io quoterei $1 però
Avatar utente
conraid
Staff
Staff
 
Messaggi: 12023
Iscritto il: mer lug 13, 2005 23:00
Località: Livorno
Nome Cognome: Corrado Franco
Slackware: current

Re: Rendere uno script ricursivo

Messaggioda anycolouryoulike » gio lug 15, 2010 14:43

conraid ha scritto:
anycolouryoulike ha scritto:Io farei così:
Codice: Seleziona tutto
IFS=$'\n'
for i in $(find . -type f -name "* *")
do
mv $i $(echo $i | tr ' ' '_')
done
Sono stato anticipato :)


io quoterei $1 però
Non ce n'è bisogno modificando l'IFS.
Avatar utente
anycolouryoulike
Packager
Packager
 
Messaggi: 1158
Iscritto il: gio ago 09, 2007 23:00
Slackware: 12.2
Kernel: 2.6.34.8
Desktop: KDE 3.5.10

Re: Rendere uno script ricursivo

Messaggioda fortea » gio lug 15, 2010 18:08

dunque dunque... innanzitutto grazie per l'attenzione. vi ho detto, sono piuttosto ignorante in materia.
In questo modo lo script è ricursivo perchè si utilizza find, giusto? e se ora non lo volessi più ricursivo si potrebbe mantenere una struttura analoga?

Comunque in questo modo mi da sempre questo errore:
Codice: Seleziona tutto
mv: cannot move `./ciao ciao/del sp 1' to `./ciao_ciao/del_sp_1': No such file or directory


Inoltre modifica anche file e directory nascosti, che sarebbe meglio non modificare perchè potrebbe appartenere a qualche programma.
fortea
Linux 1.0
Linux 1.0
 
Messaggi: 24
Iscritto il: gio lug 15, 2010 13:00
Slackware: 13.0
Kernel: 2.6.29.6
Desktop: fluxbox

Re: Rendere uno script ricursivo

Messaggioda anycolouryoulike » gio lug 15, 2010 18:50

Come è già stato detto, per rinominare anche le directory basta togliere -type f.
Se vuoi escludere i file e le directory nascosti puoi filtrare i risultati ad esempio così:
Codice: Seleziona tutto
find | sed '/\/\./d'
Avatar utente
anycolouryoulike
Packager
Packager
 
Messaggi: 1158
Iscritto il: gio ago 09, 2007 23:00
Slackware: 12.2
Kernel: 2.6.34.8
Desktop: KDE 3.5.10

Re: Rendere uno script ricursivo

Messaggioda conraid » gio lug 15, 2010 19:44

anycolouryoulike ha scritto:
conraid ha scritto:
anycolouryoulike ha scritto:Io farei così:
Codice: Seleziona tutto
IFS=$'\n'
for i in $(find . -type f -name "* *")
do
mv $i $(echo $i | tr ' ' '_')
done
Sono stato anticipato :)


io quoterei $1 però
Non ce n'è bisogno modificando l'IFS.


questa mi mancava :oops:
Avatar utente
conraid
Staff
Staff
 
Messaggi: 12023
Iscritto il: mer lug 13, 2005 23:00
Località: Livorno
Nome Cognome: Corrado Franco
Slackware: current

Re: Rendere uno script ricorsivo

Messaggioda fortea » lun lug 19, 2010 14:51

Ma l'opzione -name a cosa serve? Non riesco a capire perchè se la metto non trova le sottodirectory, mentre se non la metto trova tutti i file presenti in tutte le sottodirectory, indistantamente dal fatto che contengano la stringa cercata o meno...
Comunque ho risolto il problema utilizzando l'opzione -regex e mettendo un '.' davanti ai caratteri jolly.
Ora il problema è un altro.

Una volta trovati i file e le directory cercati, lo script comincia a modificarne il nome; per testarlo ho creato le seguenti directory nella mia home.
|-- ciao cao1
| |-- cia ciAO2
| | `-- pro prova2.txt
| `-- prov prov1.txt
Il comando mv modifica per primo il nome di "./ciao\ cao1", non riuscendo così a modificare gli altri perchè l'argomento passatogli contiene ancora il nome non modificato.

Soluzioni? L'unica che mi viene in mente è applicare più volte il find, quante volte è stato inserito dall'utente, ma è un po' spigolosa...

Grazie mille, allego il codice allo stato attuale e il messaggio d'errore:

Codice: Seleziona tutto
IFS=$'\n'
      for i in $(find $str1 -regex .*\ .* | sed '/\/\./d' )
      do
         mv -v $i $(echo $i | tr '\ ' '_')
      done


Codice: Seleziona tutto
`./ciao cao1' -> `./ciao_cao1'
mv: cannot stat `./ciao cao1/cia ciAO2': No such file or directory
mv: cannot stat `./ciao cao1/cia ciAO2/pro prova2.txt': No such file or directory
mv: cannot stat `./ciao cao1/prov prov1.txt': No such file or directory
fortea
Linux 1.0
Linux 1.0
 
Messaggi: 24
Iscritto il: gio lug 15, 2010 13:00
Slackware: 13.0
Kernel: 2.6.29.6
Desktop: fluxbox

Re: Rendere uno script ricorsivo

Messaggioda albatrosla » lun lug 19, 2010 15:30

Secondo me, fai uno script che esegue la singola operazione da fare su ciascun file, ad es.:
Codice: Seleziona tutto
#!/bin/bash
# Crea una directory tmp e copia in essa il file, argomento dello script
mkdir -p tmp
cp "$@" ./tmp

quindi lo rendi eseguibile e poi ti appoggi solo su find:
Codice: Seleziona tutto
find . -name "<pattern>" -exec script.sh {} \;

Bisogna fare attenzione alle virgolette su $@ per evitare che l'argomento passato da find allo script, qualora abbia degli spazi o altri caratteri che necessitano escaping, mandi tutto a rotoli.
albatrosla
Packager
Packager
 
Messaggi: 1294
Iscritto il: sab mar 27, 2004 0:00
Località: Bressa - Friuli / Torino
Slackware: current
Desktop: fluxbox.git

Re: Rendere uno script ricorsivo

Messaggioda targzeta » lun lug 19, 2010 16:00

Impara a leggere i manuali, non è che per ogni problemino relativo alle opzioni di find devi fare una domanda!!!
Comunque, vedi se ti può essere utile questo:
Codice: Seleziona tutto
$> mkdir -p casa/ciao\ cao1/cia\ ciAO2; touch casa/ciao\ cao1/cia\ ciAO2/pro\ prova2.txt; touch casa/ciao\ cao1/pro\ prova\ 2.txt

$> tree casa
casa/
`-- ciao cao1
    |-- cia ciAO2
    |   `-- pro prova2.txt
    `-- pro prova 2.txt

$> (IFS=$'\n'; for file in $(find casa/ -depth -name "* *"); do dir=$(dirname $file); name=$(basename $file); mv $file ${dir}/${name// /_}; done)

$> tree casa
casa/
`-- ciao_cao1
    |-- cia_ciAO2
    |   `-- pro_prova2.txt
    `-- pro_prova_2.txt

Emanuele
Linux Registered User #454438
Se pensi di essere troppo piccolo per fare la differenza, prova a dormire con una zanzara -- Dalai Lama
20/04/2013 - Io volevo Rodotà
Avatar utente
targzeta
Iper Master
Iper Master
 
Messaggi: 6200
Iscritto il: gio nov 03, 2005 14:05
Località: Carpignano Sal. (LE) <-> Pisa
Nome Cognome: Emanuele Tomasi
Slackware: current
Kernel: latest stable
Desktop: IceWM

Re: Rendere uno script ricorsivo

Messaggioda fortea » mar lug 20, 2010 12:59

spina ha scritto:Impara a leggere i manuali, non è che per ogni problemino relativo alle opzioni di find devi fare una domanda!!!


Io l'ho letto il manuale, ma non sono molto ferrato con l'inglese e in italiano non l'ho trovato... :(
Per il resto grazie mille ancora, in questo modo funziona benissimo. Ancora una domanda (certamente da ignorante): si può riutilizzare un parametro all'interno dello script passato da riga di comando nel lanciare lo script?
fortea
Linux 1.0
Linux 1.0
 
Messaggi: 24
Iscritto il: gio lug 15, 2010 13:00
Slackware: 13.0
Kernel: 2.6.29.6
Desktop: fluxbox

Re: Rendere uno script ricorsivo

Messaggioda targzeta » mar lug 20, 2010 13:29

I parametri sono acceduti tramite $i dove i è il numero del parametro che ti serve. Cerca il manuale della bash. Ad esempio se hai uno script chiamato 'casa.sh' e lo lanci con: casa.sh ciao. Allora il parametro 'ciao' lo trovi nella variabile $1.

Però ci sono altre questioni, quindi leggiti il man della bash, che esiste, anche se vecchio, in italiano.
Emanuele
Linux Registered User #454438
Se pensi di essere troppo piccolo per fare la differenza, prova a dormire con una zanzara -- Dalai Lama
20/04/2013 - Io volevo Rodotà
Avatar utente
targzeta
Iper Master
Iper Master
 
Messaggi: 6200
Iscritto il: gio nov 03, 2005 14:05
Località: Carpignano Sal. (LE) <-> Pisa
Nome Cognome: Emanuele Tomasi
Slackware: current
Kernel: latest stable
Desktop: IceWM


Torna a Programmazione

Chi c’è in linea

Visitano il forum: Nessuno e 2 ospiti

cron