Disons que j'ai 1000 fichiers .csv qui ont des noms aléatoires dans un dossier test
. et j'ai un python script script.py
. Je voudrais écrire un script bash qui transmettrait le nom de chaque fichier du dossier à script.py
puis l'exécuter. Le script bash doit donc s'exécuter script.py
1000 fois, à chaque fois avec un nom de fichier différent. , exemple, première exécution:
with open('records.csv','r') as in_file
prochaine course
with open('vertigo.csv','r') as in_file
Je sais que je pourrais le faire en python sans avoir à écrire un script bash comme
import glob
for filename in glob.glob('*.csv'):
# script here
Mais je fais quelques tests donc j'aimerais bien le faire en bash
Utilisez sys.argv[1]
pour que le nom de fichier soit extrait des arguments:
import sys
with open(sys.argv[1],'r') as in_file
Ensuite, vous pouvez utiliser différentes méthodes pour passer le nom de fichier en argument. Par exemple, avec find
:
find test/ -type f -name '*.csv' -exec /path/to/script.py {} \;
Une alternative à l’utilisation de sys.argv
consiste à utiliser argparse
. Très utile si vous avez besoin d'analyser davantage les paramètres de ligne de commande.
#!/usr/bin/env python2
import argparse
def main(files):
for f in files:
print "Would do something with", f
if __== "__main__":
parser = argparse.ArgumentParser()
parser.add_argument('file', nargs='+', help='path to the file')
args_namespace = parser.parse_args()
args = vars(args_namespace)['file']
main(args)
Exécutez-le avec Bash développant notre liste d'arguments de fichiers:
$ ./script.py *.csv
Would do something with file1.csv
Would do something with file2.csv
Would do something with file3.csv
Et fournit une aide intégrée "gratuitement":
$ ./script.py --help
usage: script.py [-h] file [file ...]
positional arguments:
file path to the file
optional arguments:
-h, --help show this help message and exit
Prolonger un peu la réponse de muru:
Pourquoi ne pas tout faire dans votre script python? Transformez les actions du script sur les fichiers en une fonction, puis exécutez le script avec l'argument répertoire:
#!/usr/bin/env python3
import os
#--- your original script, transformed into a function
def some_function(file):
print(file)
#---
# The directory with your .csv files
dr = sys.argv[1]
for f in os.listdir(dr):
file = dr+"/"+f
some_function(file)
Ou un peu plus court:
for f in os.listdir(dr):
some_function(dr+"/"+f)
Ou, si le répertoire contient également peut-être contient d'autres fichiers:
for f in [f for f in os.listdir(dr) if f.endswith(".csv")]:
some_function(dr+"/"+f)
Ensuite, exécutez-le simplement avec le répertoire en argument:
python3 <script> <directory>
Utilisez la liste sys.argv
as en fournissant tous les fichiers individuels en tant qu'arguments et demandez à votre Shell (par exemple, Bash) de le développer pour vous.
script.py
ressemble à:
#!/usr/bin/env python2
import sys
def main(files):
for f in files:
print "Would do something with", f
if __== "__main__":
files = sys.argv[1:]: # slices off the first argument (executable itself)
main(files)
Arbre de fichiers comme ceci:
.
├── file1.csv
├── file2.csv
├── file3.csv
└── script.py
0 directories, 4 files
Ensuite, rendez-le exécutable:
chmod +x script.py
Exécutez-le avec les arguments développés par le shell:
./script.py *.csv
Les sorties:
Would do something with file1.csv
Would do something with file2.csv
Would do something with file3.csv
Vous devrez récupérer le nom du fichier dans le script python pour que cela fonctionne:
#!/bin/bash
for f in *.csv; do
python script.py "$f"
done
Dans un one-liner:
for f in *.csv; do python script.py "$f"; done