2009-06-16 5 views
8

Ich habe eine große Textdatei in eine Reihe von kleineren Dateien für Leistungstests geteilt, die ich mache. Es gibt eine Reihe von Verzeichnissen wie folgt aus:Bash: Wie durchläuft man die Verzeichnisstruktur und führt Befehle aus?

/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...) 

Es ist wichtig zu beachten, dass es eine zunehmende Anzahl von Dateien in jedem Verzeichnis ist. Was ich tun muss, ist eine ausführbare Datei für jede der Textdateien in den Ausgabeverzeichnissen auszuführen. Der Befehl sieht ungefähr so ​​gegen eine einzelne Datei:

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

Hier wird der Parameter -i ist die Eingabedatei und Parameter -o ist die Ausgabestelle.

In C# würde ich über die Verzeichnisse durchlaufen die Liste der Dateien in jedem Ordner abrufen, dann durchlaufen Sie sie, um die Befehlszeilen auszuführen. Wie durchlaufe ich eine Verzeichnisstruktur wie diese mit bash und führe den Befehl mit den richtigen Parametern basierend auf dem Ort und den Dateien an diesem Ort aus?

Antwort

8

Für diese Art von Sache, die ich immer zusammen mit xargs finden verwenden:

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

Jetzt seit Ihrem Skript verarbeitet nur eine Datei zu einem Zeitpunkt, mit -exec (oder -execdir) direkt mit finden, wie bereits angedeutet, ist genauso effizient, aber ich bin zu verwenden xargs verwendet, als dass in der Regel viel mehr effizient, wenn ein Befehl eingegeben wird, der viele Argumente gleichzeitig verarbeitet. Somit ist es ein sehr nützliches Werkzeug, um in seinem Utility-Gürtel zu bleiben, also dachte ich, es sollte erwähnt werden.

7

Etwas wie:

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

dort zurück-Zecken vor finden und nach f – nikudesu

+1

für x in $ (find/home/brianonly -type f); do ... done $() ist _so_ viel lesbarer als Back-Ticks. Mein $ .02. –

+0

Ich denke, Ihr würde versuchen, die verarbeiteten Dateien zu verarbeiten. –

2

Wie andere, verwenden find(1) vorgeschlagen haben:

# 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

Aus den bereitgestellten Informationen klingt es, als wäre dies eine völlig übersichtliche Übersetzung Ihrer C# - Idee.

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