2009-06-16 7 views
8

J'ai divisé un grand fichier texte en un certain nombre d'ensembles de plus petits pour les tests de performance que je fais. Il y a un certain nombre de répertoires comme ceci:Bash: comment parcourir la structure du répertoire et exécuter des commandes?

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

Il est important de noter qu'il ya un nombre croissant de fichiers dans chaque répertoire. Ce que je dois faire est d'exécuter un exécutable contre chacun des fichiers texte dans les répertoires de sortie. La commande ressemble à ceci contre un seul fichier:

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

Ici le paramètre -i est le fichier d'entrée et le paramètre -o est l'emplacement de sortie. En C#, je ferais une boucle sur les répertoires pour obtenir la liste des fichiers dans chaque dossier, puis je ferais une boucle pour exécuter les lignes de commande. Comment puis-je parcourir une structure de répertoire comme celle-ci en utilisant bash, et exécuter la commande avec les paramètres corrects en fonction de l'emplacement et des fichiers dans cet emplacement?

Répondre

8

Pour ce genre de chose que je toujours utiliser trouver avec xargs:

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

Maintenant, depuis vos processus de script un seul fichier à la fois, en utilisant -exec (ou -execdir) directement avec trouver, comme cela a déjà suggéré, est tout aussi efficace, mais je suis habitué à l'utilisation xargs, comme c'est généralement beaucoup plus efficace lors de l'alimentation d'une commande fonctionnant sur plusieurs arguments à la fois. C'est donc un outil très utile à garder dans sa ceinture utilitaire, alors j'ai pensé qu'il devrait être mentionné.

7

Quelque chose comme:

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

il y a en arrière-tiques trouvent avant et après f – nikudesu

+1

pour x dans $ (find/home/brianonly -type f); do ... done $() est _so_ beaucoup plus lisible que les back-ticks. Mon $ .02. –

+0

Je pense que le vôtre essaierait de traiter les fichiers traités. –

2

Comme d'autres l'ont suggéré, utiliser 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

D'après les informations fournies, il semblerait que ce soit une traduction complètement simple de votre idée 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