2012-06-14 6 views
12

Estoy intentando crear una función que elimine todos los archivos que comienzan con 'prepend' desde la raíz de mi proyecto. Esto es lo que tengo hasta ahoraLlamar a rm desde el subproceso utilizando comodines no elimina los archivos

def cleanup(prepend): 
    prepend = str(prepend) 
    PROJECT_ROOT = os.path.abspath(os.path.dirname(__file__)) 
    end = "%s*" % prepend 
    cmd = 'rm' 
    args = "%s/%s" % (PROJECT_ROOT, end) 
    print "full cmd = %s %s" %(cmd, args) 
    try: 
     p = Popen([cmd, args], stdin=PIPE, stdout=PIPE, stderr=PIPE, close_fds=True).communicate()[0] 
     print "p", p 
    except Exception as e: 
     print str(e) 

No estoy teniendo un poco de suerte - no parece estar haciendo nada. ¿Tienes alguna idea de lo que podría estar haciendo mal? ¡Gracias!

+0

pienso La respuesta de Levon es el mejor enfoque, dicho esto, si quieres ver lo que está haciendo, ejecuta esto bajo 'strace (1)' con la opción de línea de comando '-f' y puedes ver el sistema exacto 'execve (2)' llamada que se está realizando. – sarnold

Respuesta

12

El problema es que está de paso dos argumentos para subprocess.Popen: rm y un camino, como /home/user/t* (si el prefijo es t). Popen luego intentará eliminar un archivo llamado exactamente de esta manera: t seguido de un asterisco al final.

Si desea utilizar Popen con el comodín, debe pasar el parámetro shell como True. En este caso, sin embargo, el comando debe ser una cadena, no una lista de argumentos:

Popen("%s %s" % (cmd, args), shell=True, stdin=PIPE, stdout=PIPE, stderr=PIPE, close_fds=True) 

(De lo contrario, the list of arguments will be given to the new shell, not to the command)

Otra solución, más seguro y más eficiente, es el uso de the glob module:

import glob 
files = glob.glob(prepend+"*") 
args = [cmd] + files 
Popen(args, stdin=PIPE, stdout=PIPE, stderr=PIPE) 

Con todo, estoy de acuerdo en que la solución de levon es la más sensata. En este caso, glob es la respuesta también:

files = glob.glob(prepend+"*") 
for file in files: 
    os.remove(file) 
14

¿Quieres que considerar este enfoque utilizando os.remove() a la eliminación de archivos en lugar de rm:

import os 
os.remove('Path/To/filename.ext') 

actualización (básicamente moviendo mi comentario de abajo en mi respuesta) :

Como os.remove() puede' t manejar comodines por sí mismo, utilizando el módulo glob para ayudar a dar una solución como se dice textualmente de este SO answer:

import glob 
import os 
for fl in glob.glob("E:\\test\\*.txt"): 
    #Do what you want with the file 
    os.remove(fl) 
+0

Definitivamente! ¿Puedo usar comodines en la llamada a eliminar? – mythander889

+1

'os.remove()' por sí solo no puede manejar comodines, pero esta respuesta SO muestra algún código usando 'os.remov e() 'con el módulo' glob' para hacer esto: http://stackoverflow.com/a/5532521/1209279 .. también se muestran otros enfoques. – Levon

+1

@ mythander889 No: los comodines son evaluados por el intérprete de comandos, y las mejores formas de hacerlo (desde una perspectiva de seguridad) no tienen envoltorio involucrado. 'import glob, os; para el nombre del archivo en glob.glob ('*. txt'): os.remove (filename) ' –

0

me gustaría probar algo como esto (que también funciona en Windows, aunque supongo que no es una preocupación para usted:

def cleanup(prepend): 
    prepend = str(prepend) 
    PROJECT_ROOT = os.path.abspath(os.path.dirname(__file__)) 
    for file_to_delete in [file for file in os.listdir(PROJECT_ROOT) if file.startswith(prepend)]: 
     os.remove(file_to_delete) 
Cuestiones relacionadas