Подтвердить что ты не робот

Вызов rm из подпроцесса с использованием подстановочных знаков не удаляет файлы

Я пытаюсь создать функцию, которая удалит все файлы, начинающиеся с "preend" из корня моего проекта. Вот что я до сих пор

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)

Мне не повезло - похоже, он ничего не делает. Есть ли у вас идеи, что я могу делать неправильно? Спасибо!

4b9b3361

Ответ 1

Проблема в том, что вы передаете два аргумента subprocess.Popen: rm и путь, например /home/user/t* (если префикс t). Popen затем попытается удалить файл с именем именно таким образом: t, за которым следует звездочка в конце.

Если вы хотите использовать Popen с подстановочным знаком, вы должны передать параметр shell как True. В этом случае, однако, команда должна быть строкой, а не списком аргументов:

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

(В противном случае список аргументов будет передан новой оболочке, а не команде)

Другим решением, более безопасным и более эффективным, является использование модуля glob:

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

В целом, однако, я согласен, что решение levon является более здравым. В этом случае glob также является ответом:

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

Ответ 2

Вы рассмотрели бы этот подход, используя os.remove() для удаления файлов вместо rm:

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

Обновить (в основном, мой комментарий ниже в мой ответ) :

Поскольку os.remove() не может самостоятельно обрабатывать подстановочные знаки, используя модуль glob, чтобы помочь получить решение как повторяющееся verbatim из этого SO answer:

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

Ответ 3

Я бы попробовал что-то вроде этого (что также работает на Windows, хотя я предполагаю, что это не проблема для вас:

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)