2011-09-06 5 views
8

posso correre questo normalmente sulla riga di comando in Linux:Python - Come chiamare i comandi di bash con pipe?

$ tar c my_dir | md5sum 

Ma quando provo a chiamarla con Python ottengo un errore:

>>> subprocess.Popen(['tar','-c','my_dir','|','md5sum'],shell=True) 
<subprocess.Popen object at 0x26c0550> 
>>> tar: You must specify one of the `-Acdtrux' or `--test-label' options 
Try `tar --help' or `tar --usage' for more information. 
+0

Perché sei hash di un file tar? Intendi cercare cambiamenti nei contenuti dei file? o verificare un file tar creato esternamente? – tMC

risposta

9

Devi usare subprocess.PIPE, anche, per dividere il comando, è necessario utilizzare shlex.split() per prevenire comportamenti strani in alcuni casi:

from subprocess import Popen, PIPE 
from shlex import split 
p1 = Popen(split("tar -c mydir"), stdout=PIPE) 
p2 = Popen(split("md5sum"), stdin=p1.stdout) 

Ma per fare un archivio e generare il suo c hecksum, dovresti usare i moduli integrati Python tarfile e hashlib invece di chiamare i comandi di shell.

+0

tarfile e hashlib sarebbe preferibile. Ma come faccio a cancellare un oggetto tarfile? – Greg

+1

@Greg non esegue l'hash dell'oggetto tarfile, apre il file risultante come qualsiasi altro file usando 'open()' e quindi esegue l'hash del suo contenuto. – MatToufoutu

+0

Ha senso. Funziona ma ottengo un valore di hash diverso rispetto al comando originale. È prevedibile? – Greg

3

Ok, io non sono sicuro perché, ma questo sembra funzionare:

subprocess.call("tar c my_dir | md5sum",shell=True) 

Qualcuno sa il motivo per cui il codice originale non funziona?

+2

il tubo | è un carattere che la shell comprende per collegare insieme gli input e gli output del comando. Non è un argomento che Tar capisce, né un comando. Stai cercando di eseguire tutto come argomento del comando tar, a meno che tu non crei una subshell. – tMC

+1

Funziona perché l'intero comando viene passato alla * shell * e la * shell * capisce il '|'. Popen chiama il processo e passa direttamente agli argomenti. Per Popen questo è controllato con 'shell =' e passando una stringa (non una lista), IIRC. –

1
>>> from subprocess import Popen,PIPE 
>>> import hashlib 
>>> proc = Popen(['tar','-c','/etc/hosts'], stdout=PIPE) 
>>> stdout, stderr = proc.communicate() 
>>> hashlib.md5(stdout).hexdigest() 
'a13061c76e2c9366282412f455460889' 
>>> 
2

quello che realmente vuole è quello di eseguire un sottoprocesso shell con il comando di shell come parametro:

>>> subprocess.Popen(['sh', '-c', 'echo hi | md5sum'], stdout=subprocess.PIPE).communicate() 
('764efa883dda1e11db47671c4a3bbd9e -\n', None)