Me gustaría ejecutar el siguiente comando UNIX en Python:

cd 2017-02-10; pwd; echo missing > 123.txt

El directorio de fecha DATE = 2017-02-10 y OUT = 123.txt ya son variables en Python, así que he intentado variaciones de

call("cd", DATE, "; pwd; echo missing > ", OUT)

Usando la función subprocess.call, pero estoy luchando por encontrar documentación para múltiples comandos UNIX a la vez, que normalmente están separados por ; o conectando con >

Hacer los comandos en líneas separadas en Python tampoco funciona porque "olvida" lo que se ejecutó en la línea anterior y se restablece la esencialidad.

0
Ben Pickering 27 oct. 2017 a las 15:54

3 respuestas

La mejor respuesta

Puede pasar un script de shell como un argumento único, con cadenas que se sustituirán como argumentos fuera de banda, de la siguiente manera:

date='2017-02-10'
out='123.txt'

subprocess.call(
  ['cd "$1"; pwd; echo missing >"$2"',  # shell script to run
   '_',                                 # $0 for that script
   date,                                # $1 for that script
   out,                                 # $2 for that script
  ], shell=True)

Esto es mucho más seguro que sustituir sus valores date y out en una cadena que el shell evalúa como código, porque estos valores se tratan como literales: A date de {{X3 }} de hecho no intentará eliminar su directorio de inicio. :)

1
Charles Duffy 27 oct. 2017 a las 12:56

Hacer los comandos en líneas separadas en Python tampoco funciona porque "olvida" lo que se ejecutó en la línea anterior y restablece la esencialidad.

Esto se debe a que si tiene llamadas separadas a subprocess.call ejecutará cada comando en su propio shell, y la llamada cd no tendrá efecto en los shells posteriores.

Una forma de evitarlo sería cambiar el directorio en el script Python antes de hacer el resto. Si esta es una buena idea depende de lo que haga el resto del script. ¿Realmente necesitas cambiar de directorio? ¿Por qué no simplemente escribir "falta" a 2017-02-10/123.txt desde Python directamente? ¿Por qué necesita la llamada pwd?

Suponiendo que está recorriendo una lista de directorios y desea generar la ruta completa de cada uno y también crear archivos con "falta" en ellos, tal vez podría hacer esto en su lugar:

import os

base = "/path/to/parent"
for DATE, OUT in [["2017-02-10", "123.txt"], ["2017-02-11", "456.txt"]]:
    date_dir = os.path.join(base, DATE)
    print(date_dir)
    out_path = os.path.join(date_dir, OUT)
    out = open(out_path, "w")
    out.write("missing\n")
    out.flush()
    out.close()

Lo anterior podría usar algún manejo de errores en caso de que no tenga permiso para escribir en el archivo o el directorio no exista, pero sus comandos de shell tampoco tienen ningún manejo de errores.

1
Wodin 29 oct. 2017 a las 07:20
>>> date = "2017-02-10"
>>> command = "cd " + date + "; pwd; echo missing > 123.txt"
>>> import os
>>> os.system(command)
0
Siva 27 oct. 2017 a las 13:06