Pagina 1 di 1

Rendere uno script ricorsivo

Inviato: gio lug 15, 2010 14:19
da fortea
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

Re: Rendere uno script ricursivo

Inviato: gio lug 15, 2010 15:30
da masalapianta
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

Re: Rendere uno script ricursivo

Inviato: gio lug 15, 2010 15:36
da anycolouryoulike
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 :)

Re: Rendere uno script ricursivo

Inviato: gio lug 15, 2010 15:39
da conraid
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ò

Re: Rendere uno script ricursivo

Inviato: gio lug 15, 2010 15:43
da anycolouryoulike
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.

Re: Rendere uno script ricursivo

Inviato: gio lug 15, 2010 19:08
da fortea
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.

Re: Rendere uno script ricursivo

Inviato: gio lug 15, 2010 19:50
da anycolouryoulike
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'

Re: Rendere uno script ricursivo

Inviato: gio lug 15, 2010 20:44
da conraid
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:

Re: Rendere uno script ricorsivo

Inviato: lun lug 19, 2010 15:51
da fortea
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

Re: Rendere uno script ricorsivo

Inviato: lun lug 19, 2010 16:30
da albatrosla
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.

Re: Rendere uno script ricorsivo

Inviato: lun lug 19, 2010 17:00
da targzeta
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

Re: Rendere uno script ricorsivo

Inviato: mar lug 20, 2010 13:59
da fortea
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?

Re: Rendere uno script ricorsivo

Inviato: mar lug 20, 2010 14:29
da targzeta
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