Passar nome do arquivo de bash para python

2

Digamos que eu tenha 1000 arquivos csv com nomes aleatórios em uma pasta test . e eu tenho um script python script.py . Eu gostaria de escrever um script bash que passaria o nome de cada arquivo na pasta para script.py e então executá-lo, portanto o script bash deve executar script.py 1000 vezes, cada vez com um nome de arquivo diferente, exemplo, primeiro executar:

with open('records.csv','r') as in_file

próxima corrida

with open('vertigo.csv','r') as in_file

Eu sei que poderia fazê-lo em python sem o incômodo de escrever um script bash como assim

import glob
for filename in glob.glob('*.csv'):
   # script here

Mas estou fazendo alguns testes, portanto, gostaria de fazer isso no bash

    
por Lynob 10.07.2015 / 19:09

5 respostas

6

Use sys.argv[1] para que o nome do arquivo seja retirado dos argumentos:

import sys

with open(sys.argv[1],'r') as in_file

Em seguida, você pode usar vários métodos para passar o nome do arquivo como um argumento. Por exemplo, com find :

find test/ -type f -name '*.csv' -exec /path/to/script.py {} \;
    
por muru 10.07.2015 / 19:19
3

A alternativa de usar sys.argv está usando argparse . Muito útil se você precisar de mais análise de parâmetro de linha de comando.

#!/usr/bin/env python2

import argparse

def main(files):
    for f in files:
        print "Would do something with", f

if __name__ == "__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)

Executando com Bash expandindo nossa lista de argumentos de arquivo:

$ ./script.py *.csv
Would do something with file1.csv
Would do something with file2.csv
Would do something with file3.csv

E fornece ajuda integrada "gratuitamente":

$ ./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
    
por gertvdijk 11.07.2015 / 02:39
2

Estendendo a resposta de muru um pouco:

Por que não fazer tudo dentro do seu script python? Transforme as ações do script nos arquivos em uma função e, em seguida, execute o script com o diretório como um argumento:

#!/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 um pouco mais curto:

for f in os.listdir(dr):
    some_function(dr+"/"+f)

Ou, se o diretório também puder conter outros arquivos:

for f in [f for f in os.listdir(dr) if f.endswith(".csv")]:
    some_function(dr+"/"+f)

Em seguida, basta executá-lo com o diretório como argumento:

python3 <script> <directory>
    
por Jacob Vlijm 10.07.2015 / 20:27
1

Você terá que recuperar o nome do arquivo no script python para que isso funcione:

#!/bin/bash
for f in *.csv; do
    python script.py "$f"
done

Em um verso:

for f in *.csv; do python script.py "$f"; done
    
por kos 10.07.2015 / 19:17
1

Use a lista sys.argv as, fornecendo todos os arquivos individuais como argumentos e deixe seu shell (por exemplo, Bash) expandi-lo para você.

script.py se parece com:

#!/usr/bin/env python2

import sys

def main(files):
    for f in files:
        print "Would do something with", f

if __name__ == "__main__":
    files = sys.argv[1:]: # slices off the first argument (executable itself)
    main(files)

Árvore de arquivos como esta:

.
├── file1.csv
├── file2.csv
├── file3.csv
└── script.py

0 directories, 4 files

Em seguida, torne-o executável:

chmod +x script.py

Execute-o com os argumentos conforme expandidos pelo shell:

./script.py *.csv

Saídas:

Would do something with file1.csv
Would do something with file2.csv
Would do something with file3.csv
    
por gertvdijk 11.07.2015 / 02:28

Tags