problemi con script bash e ricorsione

Postate qui per tutte le discussioni legate a Linux in generale.

Moderatore: Staff

Regole del forum
1) Citare sempre la versione di Slackware usata, la versione del Kernel e magari anche la versione della libreria coinvolta. Questi dati aiutano le persone che possono rispondere.
2) Per evitare confusione prego inserire in questo forum solo topic che riguardano appunto Gnu/Linux in genere, se l'argomento è specifico alla Slackware usate uno dei forum Slackware o Slackware64.
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.
Avatar utente
danix
Staff
Staff
Messaggi: 3289
Iscritto il: ven 27 ott 2006, 19:32
Nome Cognome: Danilo M.
Slackware: 64 current
Kernel: 6.12.13 x86_64
Desktop: i3
Località: Verona (VR)
Contatta:

problemi con script bash e ricorsione

Messaggio 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...
danix
danix ha scritto:non sono molto presente sul forum, e di ciò mi scuso con tutti

Avatar utente
targzeta
Iper Master
Iper Master
Messaggi: 6643
Iscritto il: gio 3 nov 2005, 14:05
Nome Cognome: Emanuele Tomasi
Slackware: 64-current
Kernel: latest stable
Desktop: IceWM
Località: Carpignano Sal. (LE) <-> Pisa

Messaggio 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

Avatar utente
danix
Staff
Staff
Messaggi: 3289
Iscritto il: ven 27 ott 2006, 19:32
Nome Cognome: Danilo M.
Slackware: 64 current
Kernel: 6.12.13 x86_64
Desktop: i3
Località: Verona (VR)
Contatta:

Messaggio 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...
danix
danix ha scritto:non sono molto presente sul forum, e di ciò mi scuso con tutti

Avatar utente
Paoletta
Staff
Staff
Messaggi: 3975
Iscritto il: lun 25 apr 2005, 0:00
Slackware: 14.2 - 64 bit
Desktop: fluxbox
Località: Varese

Messaggio 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
;)

Avatar utente
targzeta
Iper Master
Iper Master
Messaggi: 6643
Iscritto il: gio 3 nov 2005, 14:05
Nome Cognome: Emanuele Tomasi
Slackware: 64-current
Kernel: latest stable
Desktop: IceWM
Località: Carpignano Sal. (LE) <-> Pisa

Messaggio 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

Avatar utente
danix
Staff
Staff
Messaggi: 3289
Iscritto il: ven 27 ott 2006, 19:32
Nome Cognome: Danilo M.
Slackware: 64 current
Kernel: 6.12.13 x86_64
Desktop: i3
Località: Verona (VR)
Contatta:

Messaggio 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
danix
danix ha scritto:non sono molto presente sul forum, e di ciò mi scuso con tutti

Avatar utente
absinthe
Iper Master
Iper Master
Messaggi: 2354
Iscritto il: dom 15 mag 2005, 0:00
Nome Cognome: Matteo Nunziati
Slackware: 12.1 - defunct
Kernel: 2.6.32-5-amd64
Desktop: gnome
Distribuzione: debian squeeze
Località: Prato
Contatta:

Messaggio 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:

Avatar utente
danix
Staff
Staff
Messaggi: 3289
Iscritto il: ven 27 ott 2006, 19:32
Nome Cognome: Danilo M.
Slackware: 64 current
Kernel: 6.12.13 x86_64
Desktop: i3
Località: Verona (VR)
Contatta:

Messaggio 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...
danix
danix ha scritto:non sono molto presente sul forum, e di ciò mi scuso con tutti

Avatar utente
targzeta
Iper Master
Iper Master
Messaggi: 6643
Iscritto il: gio 3 nov 2005, 14:05
Nome Cognome: Emanuele Tomasi
Slackware: 64-current
Kernel: latest stable
Desktop: IceWM
Località: Carpignano Sal. (LE) <-> Pisa

Messaggio 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

Avatar utente
danix
Staff
Staff
Messaggi: 3289
Iscritto il: ven 27 ott 2006, 19:32
Nome Cognome: Danilo M.
Slackware: 64 current
Kernel: 6.12.13 x86_64
Desktop: i3
Località: Verona (VR)
Contatta:

Messaggio 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...
danix
danix ha scritto:non sono molto presente sul forum, e di ciò mi scuso con tutti

Avatar utente
Paoletta
Staff
Staff
Messaggi: 3975
Iscritto il: lun 25 apr 2005, 0:00
Slackware: 14.2 - 64 bit
Desktop: fluxbox
Località: Varese

Messaggio 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:

Avatar utente
danix
Staff
Staff
Messaggi: 3289
Iscritto il: ven 27 ott 2006, 19:32
Nome Cognome: Danilo M.
Slackware: 64 current
Kernel: 6.12.13 x86_64
Desktop: i3
Località: Verona (VR)
Contatta:

Messaggio 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??
danix
danix ha scritto:non sono molto presente sul forum, e di ciò mi scuso con tutti

Avatar utente
targzeta
Iper Master
Iper Master
Messaggi: 6643
Iscritto il: gio 3 nov 2005, 14:05
Nome Cognome: Emanuele Tomasi
Slackware: 64-current
Kernel: latest stable
Desktop: IceWM
Località: Carpignano Sal. (LE) <-> Pisa

Messaggio da targzeta »

Eh, allora non vuoi proprio imparare eh ;)?

Codice: Seleziona tutto

man bash
Spina

Avatar utente
danix
Staff
Staff
Messaggi: 3289
Iscritto il: ven 27 ott 2006, 19:32
Nome Cognome: Danilo M.
Slackware: 64 current
Kernel: 6.12.13 x86_64
Desktop: i3
Località: Verona (VR)
Contatta:

Messaggio 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...
danix
danix ha scritto:non sono molto presente sul forum, e di ciò mi scuso con tutti

Avatar utente
waka_jawaka
Linux 3.x
Linux 3.x
Messaggi: 781
Iscritto il: mer 10 ago 2005, 0:00
Nome Cognome: Alberto Palillo
Kernel: 2.6.35
Desktop: KDE 4.5
Distribuzione: Archlinux

Messaggio da waka_jawaka »

Ma siamo in Star Trek o in Guerre Stellari?!!
Razzo, non imparerò mai... :cry: :cry: :cry: :cry: :cry:

Rispondi