Pagina 1 di 2

problemi con script bash e ricorsione

Inviato: dom 21 gen 2007, 19:05
da danix
Salve a tutti,
sto cercando di creare uno script che mi permetta in un colpo solo di cambiare i permessi in un intero albero di directory distinguendo se si tratta di directory o di files, alle prime voglio dare il permesso 0755 (lettura e passaggio per chi non è il proprietario, e cioè root), mentre ai secondi 0744 (solo lettura agli utenti non root); ma qui sorgono i problemi... vi posto lo script per come l'ho scriPto :lol: , vediamo se ne riuscite a cavare qualcosa...

Codice: Seleziona tutto

#! /bin/bash

# questo script può essere lanciato solo da root e serve per settare
# correttamente i permessi della partizione di backup e tutte le 
# sottodirectory in essa contenuta


work_folder=/backup

directories=$(find $work_folder -type d)
files=$(find $work_folder -type f)

for item in $directories
do
	chmod 0755 $item
done

for item in $files
do
	chmod 0744 $item
done

exit
il problema (almeno credo) sta nel fatto che non appena vede un file che si chiama:

Codice: Seleziona tutto

/percorso/del file/nomefile
si pianta perchè nel path di quel file c'è uno spazio che bash non sa leggere... allora cosa mi sono inventato (dopo tonnellate di ricerche su zio google), con lo stesso principio ho fatto un altro script semplice semplice che dovrebbe (nelle intenzioni, la realtà è ben altra cosa...) sostituire tutti gli spazi con degli underscore, ma purtroppo non collabora... vi faccio vedere:

Codice: Seleziona tutto

directories=$(find $PWD -type d)
files=$(find $PWD -type f)
for item in $directories
do
	n=`echo "$item/" | tr '[:blank:]' '_'`
	n=${n%/}
	[[ $item == $n ]] || mv "$item" "$n"
done

for item in $files
do
	n=`echo "$item/" | tr '[:blank:]' '_'`
	n=${n%/}
	[[ $item == $n ]] || mv "$item" "$n"
done
ma anche questo si pianta per qualche motivo che non sono riuscito a capire...

:banghead: vi prego, datemi una mano...

Inviato: dom 21 gen 2007, 19:33
da targzeta
Usa l'opzione -exec di find:

Codice: Seleziona tutto

find /backup -type d -exec chmod 0755 '{}' \;
e

Codice: Seleziona tutto

find /backup -type f -exec chmod 0744 '{}' \;
Per ulteriori informazioni:

Codice: Seleziona tutto

man find
Spina

P.S. Se vuoi sapere perchè il tuo script non funziona

Codice: Seleziona tutto

man bash
vedi la variabile IFS

Inviato: dom 21 gen 2007, 19:45
da danix
spina ha scritto:Usa l'opzione -exec di find:

Codice: Seleziona tutto

find /backup -type d -exec chmod 0755 '{}' \;
e

Codice: Seleziona tutto

find /backup -type f -exec chmod 0744 '{}' \;
Per ulteriori informazioni:

Codice: Seleziona tutto

man find
Spina

P.S. Se vuoi sapere perchè il tuo script non funziona

Codice: Seleziona tutto

man bash
vedi la variabile IFS
non ho ancora provato ad usare la funzione -exec di find, ma mi sembra abbastanza chiara, ho letto però la variabile IFS di bash, e non ne ho capito nulla... mi potresti aiutare a capire??

[EDIT]

ok, la funzione -exec di find era quello di cui avevo bisogno, perfetto... resta da capire IFS... ma ci arriverò...
per quanto riguarda il secondo script, quello che dovrebbe sostituire gli spazi con gli underscore, hai idea del perchè non funziona??

grazie mille comunque...

Inviato: dom 21 gen 2007, 20:34
da Paoletta
puoi anche romperti la testa a capire perchè questo va

Codice: Seleziona tutto

#!/bin/bash 
work_folder=/backup

directories=$(find $work_folder -type d)
files=$(find $work_folder -type f) 
directories=`echo "$directories"`
files=`echo "$files"`

for item in $directories
do
   chmod 0755 $item
done

for item in $files
do
   chmod 0744 $item
done

exit
;)

Inviato: dom 21 gen 2007, 20:36
da targzeta
Il punto è che la bash va letta!!! Sono convinto che se la leggessi bene riusciresti a risolvere da te tantissimi problemi, anche perchè è veramente potente.

La shell effettua espansioni, un esempio classico è il simbolo '*' che si espande con ogni cosa. Dopo aver effettuato queste espansioni la shell deve anche capire dove finisce una parola e dove ne comincia un altra. La variabile d'ambiente IFS fa proprio questo, indica alla bash quali sono i caratteri che separano le parole. Se fai

Codice: Seleziona tutto

set | grep IFS
vedrai com'è impostata la tua IFS, che in generale vale " \t\n". Questi tre caratteri, spazio, tabulazione (\t) e new line (\n), indicano alla bash dove finisce una parola e ne comincia un altra.
Ora cerco di spiegarti con un esempio che dovrebbe fornire una risposta anche al secondo problema.

Sai cos'è un array? Vedilo come una tabella di un unica colonna e tante righe. La bash usa gli array (man bash, in inglese, quella italiana non ne parla) e questi possono essere utile per risolvere il tuo problema.
Ti faccio un esempio, se lanciamo:

Codice: Seleziona tutto

casa=($(echo -e "ciao mamma\nguarda\tcome mi diverto"))
Stiamo dicendo alla bash di crearci un array, chiamato casa, le cui righe devono essere impostate con l'output di echo (l'opzione -e serve per poter inserire i caratteri particolari \t e \n).
Se ora noi vogliamo visualizzare la prima riga dell'array facciamo:

Codice: Seleziona tutto

echo ${casa[0]};
ciao
Perchè solo ciao? Perchè la shell, dato che la variabile IFS è impostata con spazio, \t e \n, a separato tutte le "parole".
Se ora noi facciamo

Codice: Seleziona tutto

IFS=$(echo -e "\n\t");
e poi rifacciamo

Codice: Seleziona tutto

casa=($(echo -e "ciao mamma\nguarda\tcome mi diverto"));
echo ${casa[0]};
ciao mamma
Quindi, avendo detto alla bash che una parola è una sequenza di caratteri qualsiasi a parte \n e \t, questa volta non ha effettuato la stessa separazione, ma ci ha considerato il "ciao mamma" come un unica parola.
Questo vuol dire che se vuoi considerare lo spazio come facente parte di una parola, basta modificare la variabile IFS.

Spero di essere stato utile, non mi prolungo perchè ho notato che post lunghi non sono mai letti fino in fondo (è anche per questo che molti non leggono il manuale della bash).

Spina

P.S. Per confonderti ancora (quando poi leggerai il man della bash capirai) ti faccio vedere cosa succede se modifichiamo la variabile in questo modo:

Codice: Seleziona tutto

IFS=$(echo -e "\t\n");
echo ${casa[0]};
ciao mamma
guarda
perchè stavolta ha considerato "ciao mamma\nguarda" come un unica parola? Eppure noi gli abbiamo detto di separare le parole con il carattere "\n". Ma glielo abbiamo detto davvero? ;) man bash

Inviato: dom 21 gen 2007, 22:02
da danix
grazie mille a tutti, siete davvero grandi, comunque, per inciso io leggo anche i post lunghissimi, per quanto riguarda IFS nel man bash non mi erano chiare alcune cose ma era probabilmente dovuto a qualche malcomprensione dall'inglese... la prossima volta studierò meglio...

ancora grazie mille per la pazienza

Inviato: lun 22 gen 2007, 8:55
da absinthe
Paoletta ha scritto:puoi anche romperti la testa a capire perchè questo va

Codice: Seleziona tutto

#!/bin/bash 
work_folder=/backup

directories=$(find $work_folder -type d)
files=$(find $work_folder -type f) 
directories=`echo "$directories"`
files=`echo "$files"`

for item in $directories
do
   chmod 0755 $item
done

for item in $files
do
   chmod 0744 $item
done

exit
;)
funziona davvero?! mitico! :shock:

Inviato: lun 22 gen 2007, 12:05
da danix
Fermo restando la funzione -exec di find, qualcuno mi sa spiegare cosa c'è di diverso tra lo script di Paoletta e il mio che ne permette il funzionamento nel primo caso e il non funzionamento nel secondo??

ve li metto vicini per semplificare le cose..

Questo è il mio:

Codice: Seleziona tutto

#! /bin/bash

# questo script può essere lanciato solo da root e serve per settare
# correttamente i permessi della partizione di backup e tutte le
# sottodirectory in essa contenuta


work_folder=/backup

directories=$(find $work_folder -type d)
files=$(find $work_folder -type f)

for item in $directories
do
   chmod 0755 $item
done

for item in $files
do
   chmod 0744 $item
done

exit 
Questo invece è quello di Paoletta:

Codice: Seleziona tutto

#!/bin/bash
work_folder=/backup

directories=$(find $work_folder -type d)
files=$(find $work_folder -type f)
directories=`echo "$directories"`
files=`echo "$files"`

for item in $directories
do
   chmod 0755 $item
done

for item in $files
do
   chmod 0744 $item
done

exit 
L'unica cosa che mi è saltata subito all'occhio è il fatto che Paoletta da un echo delle 2 variabili find, ma anche senza echo find mostra i risultati, probabilmente il ciclo for successivo ha bisogno di quell'echo per funzionare, ma per quale motivo??

speriamo di riuscire a scoprire l'arcano...

Inviato: lun 22 gen 2007, 13:46
da targzeta
A me non funziona, ed in effetti, se funziona vorrei sapere anche io perchè ;).

Codice: Seleziona tutto

find . -type d;
./ciao mamma
./ciao mamma/guarda
./ciao mamma/guarda/come mi diverto
Ora con questo script:

Codice: Seleziona tutto

#!/bin/bash 
work_folder=.

directories=$(find $work_folder -type d) 
directories=`echo "$directories"` 

for item in $directories 
do 
      echo ${item}
done 

exit
ecco l'output:

Codice: Seleziona tutto

.
./ciao
mamma
./ciao
mamma/guarda
./ciao
mamma/guarda/come
mi
diverto
Come si vede, ha ancora diviso le parole considerando lo spazio un end-of-word.

Spina

Inviato: lun 22 gen 2007, 17:28
da danix
non lo avevo ancora testato in quanto ho risolto il problema usando la funzione -exec di find, ma ora stavo guardando e neanche da me funziona...
a questo punto chiedo a paoletta... potresti fare una prova con un percorso con dentro degli spazi tipo:

Codice: Seleziona tutto

/percorso/del file/nomefile
e farci sapere...

grazie...

Inviato: lun 22 gen 2007, 23:35
da Paoletta
ciao danix, in effetti quando ci sono gli sapzi di mezzo il mio script non funziona; ieri leggendo il tuo primo post, o perchè ero cotta io o perchè non l'avevi ancora scritto tu quando l'ho letto io, non ho letto che il problema riguardava gli spazi; sorry!! ;) :banghead:

Inviato: mar 23 gen 2007, 14:32
da danix
no problem paoletta, tanto ho risolto usando la funzione -exec di find...

ho una domanda però, quando imposto in uno script una variabile come ad esempio $IFS, una volta lanciato lo script questa rimane impostata nel sistema o rimane così solo durante l'esecuzione dello script??

Inviato: mar 23 gen 2007, 14:41
da targzeta
Eh, allora non vuoi proprio imparare eh ;)?

Codice: Seleziona tutto

man bash
Spina

Inviato: mar 23 gen 2007, 17:14
da danix
ho fatto quella domanda dopo aver letto questo nel man bash:

Codice: Seleziona tutto

Compound Commands
       A compound command is one of the following:

       (list) list is executed in a subshell environment (see COMMAND  EXECUTION  ENVIRONMENT  below).
              Variable  assignments  and  builtin  commands that affect the shell's environment do not
              remain in effect after the command completes.  The return status is the exit  status  of
              list.
e volevo capire meglio...

Inviato: mar 23 gen 2007, 21:30
da waka_jawaka
Ma siamo in Star Trek o in Guerre Stellari?!!
Razzo, non imparerò mai... :cry: :cry: :cry: :cry: :cry: