scripting bash -- confronto files e directory

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.
Rispondi
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:

scripting bash -- confronto files e directory

Messaggio da danix »

Ciao a tutti...
sto scrivendo uno scriptino che dovrebbe controllare il contenuto di 2 directory identiche, una di produzione e una il prodotto finito, per confrontare i contenuti avevo pensato di appoggiarmi a stat, solo che una volta ottenuta la data dell'ultima modifica su un file non ho idea di come fare per confrontarla con quella del suo omologo "di produzione"...

avevo pensato una cosa del genere (molto semplificato)

Codice: Seleziona tutto

fileA=/percorso/del/file/di/produzione
fileB=/percorso/del/file/finito

LastModA=$(stat --format=%y $fileA)
LastModB=$(stat --format=$y $fileB)
Ma poi come faccio a confrontare $LastModA e $LastModB??

Se avete qualche metodo migliore ovviamente il suggerimento è ben accetto, così come è ben accetto il vostro aiuto in questo caso...

Grazie mille a tutti
A presto...
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 »

ma tu cosa vuoi vedere?
- Qual'è il più recente?
- Se sono differenti?

Per il primo caso ti conviene utilizzare il %Y e poi confrontare i due risultati, quello maggiore è il più recente.

Per il secondo caso puoi utilizzare il programma "diff".

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 »

ciao Spina, grazie della risposta, a me interessava sapere qual'è il più recente tra i 2 files, ieri avevo letto di %Y che mi restituisce l'output in secondi a partire da epoch ma non avevo realizzato il modo in cui usarlo...
Avrei solo un altro piccolo dubbio, che differenza c'è tra %y e %z?? y dice l'ultima modifica, mentre z l'ultimo cambiamento... ma non riesco a scorgere la differenza tra le 2 cose...

Grazie comunque per avermi illuminato :D
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 »

danix85 ha scritto:...che differenza c'è tra %y e %z?? y dice l'ultima modifica, mentre z l'ultimo cambiamento...
Bhé, l'ultima modifica si intende al contenuto del file, mentre l'ultimo cambiamento si intende all'inode del file.
Ricordando che l'inode contiene tutte le info sul file, come tempi, lunghezza, permessi, etc..si ha ad esempio che con:

Codice: Seleziona tutto

$> touch casa
$> stat --printf="File  -> %y\nInode -> %z" casa 
File  -> 2007-08-26 02:04:54.000000000 +0200
Inode -> 2007-08-26 02:04:54.000000000 +0200
i tempi sono uguali perchè è cambiato sia il contenuto del file (è stato creato) che dell'inode (che è stato inizializzato).

Modificando il contenuto del file con:

Codice: Seleziona tutto

$> echo ciao > casa
$> stat --printf="File  -> %y\nInode -> %z" casa 
File  -> 2007-08-26 02:05:14.000000000 +0200
Inode -> 2007-08-26 02:05:14.000000000 +0200
ovviamente i tempi rimangono uguali, perchè modificando il contenuto del file viene modificato anche l'inode (ad esempio è cambiata la lunghezza del file, ma anche lo stesso tempo di ultima modifica è stato cambiato)

Mentre con:

Codice: Seleziona tutto

$> chmod a+w casa
$> stat --printf="File  -> %y\nInode -> %z" casa
File  -> 2007-08-26 02:05:14.000000000 +0200
Inode -> 2007-08-26 02:05:33.000000000 +0200
cambia solo l'inode (sono cambiati i permessi al file) mentre il contenuto del file non viene modificato.

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 »

ciao Spina, grazie mille del chiarimento...
approfitto per postare lo script che sto scrivendo sperando che qualcuno abbia voglia di aiutarmi, mi sono arginato e mi sembra di girare attorno alla soluzione senza però riuscire a coglierla...

Codice: Seleziona tutto

#! /bin/bash

# questo script si occupa di aggiornare tutti i files contenuti nella directory /home/www con quelli
# contenuti nella directory /home/danix/Documents/website ogni volta che il computer viene spento.
# Quest'operazione è possibile grazie al file /etc/rc.d/rc.local_shutdown.

### DEFINISCO LE VARIABILI
WD=/home/danix/Documents/website
DD=/home/www
tempfile=/tmp/websiteupdater


# prima di iniziare pulisco gli eventuali files temporanei
# rimasti dall'ultima esecuzione
if [[ -f $tempfile ]]
then
        rm $tempfile
        touch $tempfile
else
        touch $tempfile
fi

# creo le variabili relavite alla destdir
d_files=$(find $DD -type f)
d_dirs=$(find $DD -type d)

# creo le variabili relative alla workdir
w_files=$(find $WD -type f)
w_dirs=$(find $WD -type d)

# inizio con i cicli che mi restituiranno il file con i percorsi
# dei files da aggiornare
for dirW in $w_dirs
do
        Wdirectory=$(ls $dirW)
        for Witem in $Wdirectory
        do
                LastModW=$(stat -c %Y $dirW/$Witem)
                echo $dirW/$Witem $LastModW >> $tempfile
        done
done

for dirD in $d_dirs
do
        Ddirectory=$(ls $dirD)
        for Ditem in $Ddirectory
        do
                LastModD=$(stat -c %Y $dirD/$Ditem)
                echo $dirD/$Ditem $LastModD >> $tempfile
        done
done

tot_line=$(cat $tempfile | wc -l)
i=1

W_temp=$(cat $tempfile |grep $WD)
D_temp=$(cat $tempfile |grep $DD)


while [[ $i -lt $tot_line ]]
do
        line=$(cat $tempfile |cut -d"
" -f$i)
        filename=$(basename `echo "$line" |cut -d" " -f1`)
        value=$(echo "$line" |cut -d" " -f2)
        echo "Questo è il valore di $filename: $value"
        let "i += 1"
done

Ho scritto molte variabili che non uso, ma praticamente in questo script sto mettendo tutto quello che mi viene in mente e forse è anche per questo che non riesco a venirne a capo... In pratica non riesco a fargli paragonare 2 files uguali ma provenienti da dir diverse in base alla loro ultima modifica...

Vorrei fargli fare una cosa simile a quei 2 cicli for all'inizio, ma con il confronto dei valori... avevo pensato anche di definire una funzione di controllo, ma anche li mi sono arginato perchè non so cosa passargli come argomento... Sopratutto in previsione del fatto che le directory non manterranno sempre lo stesso numero di files e che qualche volta la workdir avrà più o meno files della destdir...

Qualcuno sa indirizzarmi un po' più vicino alla riva dal momento che mi trovo parecchio in alto mare???

Grazie mille a tutti...
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 »

Ma tu vuoi che le due directory abbiano gli stessi file, e che siano quelli più aggiornati?
Se è così, prova rsync(1). Guarda qui:

Codice: Seleziona tutto

$> mkdir casa
$> mkdir casa1
$> echo "sono un salame" > casa/file
$> echo "non essere cattivo" > casa/file1
$> echo "non sono un salame" > casa1/file
$> echo "fai il bravo" > casa1/file2
La situazione è questa:

Codice: Seleziona tutto

ls -l *
casa:
totale 8
4 -rw-r--r-- 1 spina users 1 2007-08-26 07:36 file
4 -rw-r--r-- 1 spina users 1 2007-08-26 07:36 file1

casa1:
totale 8
4 -rw-r--r-- 1 spina users 1 2007-08-26 07:37 file
4 -rw-r--r-- 1 spina users 1 2007-08-26 07:37 file2
- il file "file" è presente in entrambe le directory ma è più aggiornato in "casa1".
- il file "file1" è presente solo in "casa"
- il file "file2" è presente solo in "casa1"

Noi vogliamo che alla fine le due directory contengano tutte e due gli stessi file e che il file "file" sia quello della directory "casa1" giusto?
Ecco qui:

Codice: Seleziona tutto

$> rsync -au casa1/ casa/
$> rsync -au casa/ casa1/
$> ls -l *
casa:
totale 12
4 -rw-r--r-- 1 spina users 1 2007-08-26 07:37 file
4 -rw-r--r-- 1 spina users 1 2007-08-26 07:36 file1
4 -rw-r--r-- 1 spina users 1 2007-08-26 07:37 file2

casa1:
totale 12
4 -rw-r--r-- 1 spina users 1 2007-08-26 07:37 file
4 -rw-r--r-- 1 spina users 1 2007-08-26 07:36 file1
4 -rw-r--r-- 1 spina users 1 2007-08-26 07:37 file2
Nota i tempi, vedi che sono corretti? comunque, per sicurezza:

Codice: Seleziona tutto

$> cat casa/file
non sono un salame

$> cat casa1/file
non sono un salame
Coerentemente a quanto si voleva.

Spina

P.S. Se vuoi fare il tuo script, io ti consiglio di crearti file temporanei diversi:
- uno che contenga l'elenco ordinato dei file della 1° dir
- uno che contenga l'elenco ordinato dei file della 2°dir
Poi usando "comm".
- uno che contenga l'elenco dei file comuni ad entrambe
- uno che contenga i file che sono solo nella prima dir
- uno che contenga i file che sono solo nella seconda dir
e per i file contenuti in entrambe le dir puoi ragionare come hai fatto tu. Io comunque lascerei perdere, meglio usare dei tool già pensati, fatti e collaudati non trovi?

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 »

ti ringrazio ancora per l'aiuto che mi stai dando, e concordo ovviamente con te sul fatto di usare rsync che è fatto proprio per questo piuttosto che buttare via energie inutili in uno script che non fa niente di più...
Stavo creando lo script semplicemente perchè non conoscevo rsync e non sono riuscito a fare la ricerca giusta su google, di conseguenza non mi è mai saltato davanti e quindi mi stavo organizzando col poco che so... :)

Grazie mille per l'aiuto...

A presto...
danix
danix ha scritto:non sono molto presente sul forum, e di ciò mi scuso con tutti

Avatar utente
IceSlack
Linux 4.x
Linux 4.x
Messaggi: 1313
Iscritto il: dom 30 ott 2005, 13:27

Re: scripting bash -- confronto files e directory

Messaggio da IceSlack »

danix85 ha scritto:Ciao a tutti...
sto scrivendo uno scriptino che dovrebbe controllare il contenuto di 2 directory identiche, una di produzione e una il prodotto finito, per confrontare i contenuti avevo pensato di appoggiarmi a stat, solo che una volta ottenuta la data dell'ultima modifica su un file non ho idea di come fare per confrontarla con quella del suo omologo "di produzione"...

avevo pensato una cosa del genere (molto semplificato)

Codice: Seleziona tutto

fileA=/percorso/del/file/di/produzione
fileB=/percorso/del/file/finito

LastModA=$(stat --format=%y $fileA)
LastModB=$(stat --format=$y $fileB)
Ma poi come faccio a confrontare $LastModA e $LastModB??

Se avete qualche metodo migliore ovviamente il suggerimento è ben accetto, così come è ben accetto il vostro aiuto in questo caso...

Grazie mille a tutti
A presto...
fai diventare le date con la unix time stamp epoch, tipo 9028340983927489 == 294023890480 cioe' in milli secondi o seno' formatta la data tipo 20072007 e le confronti cosi' facebndo hai un normale numero

Avatar utente
submax82
Staff
Staff
Messaggi: 3202
Iscritto il: mer 31 ago 2005, 0:00
Desktop: xfce
Distribuzione: SalixOS
Contatta:

Messaggio da submax82 »

potrei usare la cosa per individuare l'ultimo pacchetto tgz installato... forse mi torna utile per kernelpkg ma è il metodo conveniente o c'è qualcosa di più veloce per vedere il file più recente di una directory!??

Mario Vanoni
Iper Master
Iper Master
Messaggi: 3174
Iscritto il: lun 3 set 2007, 21:20
Nome Cognome: Mario Vanoni
Slackware: 12.2
Kernel: 3.0.4 statico
Desktop: fluxbox/seamonkey
Località: Cuasso al Monte (VA)

Messaggio da Mario Vanoni »

submax82 ha scritto:potrei usare la cosa per individuare l'ultimo pacchetto tgz installato... forse mi torna utile per kernelpkg ma è il metodo conveniente o c'è qualcosa di più veloce per vedere il file più recente di una directory!??
ls -alt

Mario Vanoni

Avatar utente
submax82
Staff
Staff
Messaggi: 3202
Iscritto il: mer 31 ago 2005, 0:00
Desktop: xfce
Distribuzione: SalixOS
Contatta:

Messaggio da submax82 »

Mario Vanoni ha scritto:
submax82 ha scritto:potrei usare la cosa per individuare l'ultimo pacchetto tgz installato... forse mi torna utile per kernelpkg ma è il metodo conveniente o c'è qualcosa di più veloce per vedere il file più recente di una directory!??
ls -alt

Mario Vanoni
quindi così

Codice: Seleziona tutto

ls -t /var/log/packages/ | head -n 1
grazie... ottima idea! però è la data dell'ultima modifica non della creazione...

Mario Vanoni
Iper Master
Iper Master
Messaggi: 3174
Iscritto il: lun 3 set 2007, 21:20
Nome Cognome: Mario Vanoni
Slackware: 12.2
Kernel: 3.0.4 statico
Desktop: fluxbox/seamonkey
Località: Cuasso al Monte (VA)

Messaggio da Mario Vanoni »

submax82 ha scritto:
Mario Vanoni ha scritto:
submax82 ha scritto:potrei usare la cosa per individuare l'ultimo pacchetto tgz installato... forse mi torna utile per kernelpkg ma è il metodo conveniente o c'è qualcosa di più veloce per vedere il file più recente di una directory!??
ls -alt

Mario Vanoni
quindi così

Codice: Seleziona tutto

ls -t /var/log/packages/ | head -n 1
grazie... ottima idea! però è la data dell'ultima modifica non della creazione...
NI, ma anche dell'ultimo file creato.

ls -alt | less
touch fantasia_tua
ls -alt | less

Mario Vanoni

Avatar utente
gallows
Staff
Staff
Messaggi: 3471
Iscritto il: lun 20 set 2004, 0:00
Desktop: cwm
Distribuzione: OpenBSD
Località: ~/
Contatta:

Messaggio da gallows »

submax82 ha scritto:grazie... ottima idea! però è la data dell'ultima modifica non della creazione...

Non puoi. Da /usr/include/asm-i386/stat.h :

Codice: Seleziona tutto

struct stat {
  [...]
        unsigned long  st_atime;
        unsigned long  st_atime_nsec;
        unsigned long  st_mtime;
        unsigned long  st_mtime_nsec;
        unsigned long  st_ctime;
        unsigned long  st_ctime_nsec;
[...]
};
st_atime -> accesso
st_mtime -> modifica
st_ctime -> cambiamento

Rispondi