web-dev-qa-db-fra.com

Passer le nom de fichier de bash à python

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

2
Lynob

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 {} \;
6
muru

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
3
gertvdijk

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>
2
Jacob Vlijm

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
1
gertvdijk

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
1
kos