2009-06-16 6 views
8

Ho diviso un grande file di testo in un numero di insiemi di quelli più piccoli per il test delle prestazioni che sto facendo. Ci sono una serie di directory in questo modo:Bash: come attraversare la struttura delle directory ed eseguire i comandi?

/home/brianly/output-02 (contains 2 files myfile.chunk.00 and myfile.chunk.01) 
/home/brianly/output-04 (contains 4 files...) 
/home/brianly/output-06 (contains 6 files...) 

E 'importante notare che v'è un numero crescente di file in ogni directory. Quello che devo fare è eseguire un eseguibile su ciascuno dei file di testo nelle directory di output. Il comando simile a questa contro un singolo file:

./myexecutable -i /home/brianly/output-02/myfile.chunk.00 -o /home/brianly/output-02/myfile.chunk.00.processed 

Qui il parametro -i è il file di input e il parametro -o è la posizione di uscita.

In C# I loop sulle directory ottengono l'elenco dei file in ogni cartella, quindi eseguono il loop su di essi per eseguire le righe di comando. Come si attraversa una struttura di directory come questa usando bash ed eseguire il comando con i parametri corretti in base alla posizione e ai file in quella posizione?

risposta

8

Per questo genere di cose che ho sempre usare trovare insieme xargs:

$ find output-* -name "*.chunk.??" | xargs -I{} ./myexecutable -i {} -o {}.processed 

Ora da quando i processi di script un solo file alla volta, utilizzando -exec (o -execdir) direttamente con trovare, come già suggerito, è altrettanto efficiente, ma io sono abituato ad usare xargs, in quanto questo è generalmente molto più efficiente quando si alimenta un comando che funziona su molti argomenti contemporaneamente. Quindi è uno strumento molto utile da tenere nella propria cintura di sicurezza, quindi ho pensato che dovesse essere menzionato.

7

Qualcosa di simile:

for x in `find /home/brianonly -type f` 
do 
./yourexecutable -i $x -o $x.processed 
done 
+0

ci sono back-zecche prima di trovare e dopo f – nikudesu

+1

for x in $ (find/home/brianonly tipo f); do ... done $() è molto più leggibile di back-ticks. I miei $ .02. –

+0

Penso che il tuo proverebbe a elaborare i file elaborati. –

2

Come altri hanno suggerito, utilizzare find(1):

# Find all files named 'myfile.chunk.*' but NOT named 'myfile.chunk.*.processed' 
# under the directory tree rooted at base-directory, and execute a command on 
# them: 
find base-directory -name 'output.*' '!' -name 'output.*.processed' -exec ./myexecutable -i '{}' -o '{}'.processed ';' 
1

Dalle informazioni fornite, sembra che questa sarebbe una traduzione completamente diretta della tua idea di C#.

for i in /home/brianly/output-*; do 
    for j in "$i/"*.[0-9][0-9]; do 
     ./myexecutable -i "$j" -o "$j.processed" 
    done 
done