Domanda

Sto cercando di fare ciò che penso sia una cosa semplice sotto Linux. Ho uno script bash che esegue vari programmi di test e voglio determinare quali file nella directory corrente sono stati creati dai programmi di test. Quindi sto facendo qualcosa del genere:

touch timestamp-file
run the test
find -newer timestamp-file -type f > list-of-files
rm -f timestamp-file

Si scopre che la granularità di find -newer è scarsa, quindi ciò che accade in genere è che alcuni file generati dal programma di test vengono visualizzati come OLDER rispetto al file timestamp. Quindi ho provato questo:

ls -tr1 | sed '1,/timestamp-file/d'

per generare lo stesso elenco. Questo di solito funziona, ma non sempre. Finisco ancora con la situazione in cui i file generati dal test appaiono più vecchi del file timestamp.

Grazie!

P.S. Posso farlo in un altro modo prendendo due istantanee della directory, una prima dell'esecuzione del programma di prova, quindi una dopo e confrontandole. Tutti i file nel secondo elenco che non sono nel primo devono essere stati creati dal programma di test (non mi occupo di lavori in background o di altri utenti che scrivono nella directory). Ma questo metodo non è quello che voglio perché se un file di output non è stato rimosso prima di eseguire il test (dovrebbero essere, ma in alcuni casi potrebbero non esserlo), questo metodo dirà che non è stato creato dal programma di test perché era nella directory prima dell'esecuzione del programma di test.

È stato utile?

Soluzione

Prendi i nomi dei file di tutti i file prima dell'esecuzione, ma includi i loro timestamp:

find -printf '%p %T@\n' | sort > file1

Se non hai quell'opzione find disponibile, puoi usare stat anche per quel lavoro:

find -print0 | xargs -0 stat -c "%n %Y" | sort > file1

E dopo l'esecuzione a file2. Quindi utilizzare

comm -1 -3 file1 file2

E ti mostrerà le righe univoche a %T@, che devono essere nuovi file se non sbaglio. Se esistessero prima, il loro tempo di modifica sarà cambiato, cosa che è curata dalla cosa <=> (stampa il numero di secondi dal 1970):

[js@HOST2 cpp]$ find -printf '%p %T@\n' | sort > file1
[js@HOST2 cpp]$ echo foo>bar
[js@HOST2 cpp]$ echo foo>baz
[js@HOST2 cpp]$ find -printf '%p %T@\n' | sort > file2
[js@HOST2 cpp]$ comm -1 -3 file1 file2
. 1230947309.0000000000
./bar 1230947308.0000000000
./baz 1230947309.0000000000
./file2 1230947315.0000000000
[js@HOST2 cpp]$ find -printf '%p %T@\n' | sort > file1
[js@HOST2 cpp]$ echo lol>bar
[js@HOST2 cpp]$ find -printf '%p %T@\n' | sort > file2
[js@HOST2 cpp]$ comm -1 -3 file1 file2
./bar 1230947359.0000000000
./file2 1230947362.0000000000
[js@HOST2 cpp]$`

Altri suggerimenti

Puoi effettivamente usare il tocco per forzare i timestamp di tutti i file correnti nella directory nel lontano passato, come:

touch -t 200801010000.00 *

Se lo fai prima di eseguire il test, dovrebbe esserci una differenza più che sufficiente nel tempo per " find -newer " raccoglierlo. Se la granularità era di due minuti, è possibile impostare tutti i file correnti su dieci minuti fa, il file timestamp su 5 minuti fa, quindi eseguire il test.

Quindi il tuo script diventa:

touch -t (current time - 10 minutes) *
touch -t (current time -  5 minutes) timestamp-file
run the test
find -newer timestamp-file -type f > list-of-files
rm -f timestamp-file

Supponendo che tu abbia una buona installazione di Perl, puoi fare quanto segue per ottenere 5 minuti fa (o usare -600 per 10 minuti) nel formato corretto per " date -t " ;:

use Date::Manip;
print UnixDate(DateCalc(ParseDateString("now"),"-300"),"%Y%m%d%H%M.%S") . "\n";

Se, per qualche motivo, non ti è permesso cambiare i timestamp, usa:

sleep 300
touch timestamp-file
sleep 300
run the test
find -newer timestamp-file -type f > list-of-files
rm -f timestamp-file

che ha lo stesso effetto, ma ti dà dieci minuti per andare a prendere un caffè (o il tuo veleno preferito se non sei un bevitore di caffè).

Se consideri come viene implementato find(1), sarà chiaro perché a volte questo potrebbe non funzionare come previsto. Ecco un suggerimento:

  $ touch timestamp ; touch newer ; find . -newer timestamp 
  $ rm timestamp newer
  $ touch timestamp ; sleep 1 ; touch newer ; find . -newer timestamp
  .
  ./newer
  $

stat(2) ottiene i valori mtime / ctime / atime del file utilizzando la chiamata di sistema struct stat. Ecco gli elementi di <sys/stat.h> da time_t (Linux):

  time_t    st_atime;   /* time of last access */
  time_t    st_mtime;   /* time of last modification */
  time_t    st_ctime;   /* time of last status change */

Su Linux (e in generale unices) -newer è un numero intero che rappresenta " secondi dall'inizio del 1970 " ;. Pertanto, la granularità più fine che <=> può comprendere è solo un secondo.

Perché non creare una directory temporanea in cui eseguire i test? Utilizza un nome basato su data e ora nella directory per tenere traccia di quali risultati si sono verificati quando, e semplicemente eliminare l'intera directory al termine.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top