Вызов 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)
Мне не повезло - похоже, он ничего не делает. Есть ли у вас идеи, что я могу делать неправильно? Спасибо!
Ответы
Ответ 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)