2012-06-14 14 views
12

Próbuję zbudować funkcję, która usunie wszystkie pliki zaczynające się od "przedrostek" z katalogu głównego mojego projektu. Oto, co mam do tej poryWywołanie rm z podprocesu przy użyciu symboli wieloznacznych nie powoduje usunięcia plików

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) 

Nie mam szczęścia - to chyba nic nie robi. Czy masz jakieś pomysły, co mogę robić źle? Dziękuję Ci!

+0

myślę Odpowiedź Levona jest lepszym podejściem, mówiąc, jeśli chcesz zobaczyć, co to robi, uruchom to pod 'strace (1)' opcją linii '-f' i możesz zobaczyć dokładny system' execve (2) ' Zadzwoń, że jest wykonywany – sarnold

Odpowiedz

12

Problemem jest to, że trzeba przejechać dwa argumenty do subprocess.Popen: rm i ścieżkę, takich jak /home/user/t* (jeśli prefiks jest t). Popen następnie spróbuje usunąć plik o nazwie dokładnie w ten sposób: t a następnie gwiazdka na końcu.

Jeśli chcesz używać Popen z symbolem wieloznacznym, należy podać parametr shell jako True. W tym przypadku jednak, komenda powinna być ciągiem, a nie lista argumentów:

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

(Inaczej the list of arguments will be given to the new shell, not to the command)

Innym rozwiązaniem, bezpieczniejsze i bardziej efektywne jest użycie the glob module:

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

Podsumowując, zgadzam się, że rozwiązanie lewonowe jest bezpieczniejsze. W tym przypadku, glob to odpowiedź zbyt:

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

Czy uważa to podejście za pomocą os.remove() do usuwania plików zamiast rm:

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

Aktualizacja (w zasadzie porusza mój komentarz od dołu do mojego odpowiedź) :

As os.remove() może” • samodzielnie posługuj się znakami wieloznacznymi, korzystając z modułu glob, aby uzyskać rozwiązanie, które będzie wielokrotnie powtarzane z tego 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

Zdecydowanie! Czy mogę używać symboli wieloznacznych w wywołaniu usunięcia? – mythander889

+1

'os.remove()' samo nie może obsługiwać symboli wieloznacznych, ale ta odpowiedź SO pokazuje kod za pomocą 'os.remov e() 'z modułem' glob' do zrobienia właśnie tego: http://stackoverflow.com/a/5532521/1209279 .. są również inne podejścia pokazane. – Levon

+1

@ mythander889 Nie - symbole wieloznaczne są oceniane przez powłokę, a najlepsze sposoby robienia tego (z punktu widzenia bezpieczeństwa) nie obejmują powłoki. 'import glob, os; dla pliku w glob.glob ('*. txt'): os.remove (nazwa pliku) ' –

0

chciałbym spróbować coś takiego (który działa również na Windows, ale zgaduję, że nie jest to problem dla ciebie:

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) 
Powiązane problemy