使用通配符从子进程调用rm不会删除文件

时间:2021-12-30 20:58:47

I'm trying to build a function that will remove all the files that start with 'prepend' from the root of my project. Here's what I have so far

我正在尝试构建一个函数,它将从项目的根目录中删除所有以'prepend'开头的文件。这是我到目前为止所拥有的

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)

I'm not having any luck -- it doesn't seem to be doing anything. Do you have any ideas what I might be doing wrong? Thank you!

我没有运气 - 它似乎没有做任何事情。你有什么想法我可能做错了吗?谢谢!

3 个解决方案

#1


14  

The problem is that you are passing two arguments to subprocess.Popen: rm and a path, such as /home/user/t* (if prefix is t). Popen then will try to remove a file named exactly this way: t followed by an asterisk at the end.

问题是你将两个参数传递给subprocess.Popen:rm和一个路径,例如/ home / user / t *(如果prefix是t)。然后Popen将尝试删除一个名称完全相同的文件:t后面跟一个星号。

If you want to use Popen with the wildcard, you should pass the shell parameter as True. In this case, however, the command should be a string, not a list of arguments:

如果要将Popen与通配符一起使用,则应将shell参数作为True传递。但是,在这种情况下,命令应该是字符串,而不是参数列表:

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

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

(否则,参数列表将被赋予新shell,而不是命令)

Another solution, safer and more efficient, is to use the glob module:

另一个更安全,更高效的解决方案是使用glob模块:

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

All in all, however, I agree that levon solution is the saner one. In this case, glob is the answer too:

总而言之,我同意levon解决方案更为理智。在这种情况下,glob也是答案:

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

#2


14  

Would you consider this approach using os.remove() to deleting files instead of rm:

您是否会考虑使用os.remove()来删除文件而不是rm:

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

Update (basically moving my comment from below into my answer):

更新(基本上将我的评论从下面移到我的答案中):

As os.remove() can't handle wildcards on its own, using the glob module to help will yield a solution as repeated verbatim from this SO answer:

由于os.remove()无法自己处理通配符,因此使用glob模块来帮助将产生一个解决方案,如同这个SO答案一样:

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

#3


0  

I would try something like this (which also works on Windows, though I'm guessing that's not a concern for you:

我会尝试这样的东西(这也适用于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)

#1


14  

The problem is that you are passing two arguments to subprocess.Popen: rm and a path, such as /home/user/t* (if prefix is t). Popen then will try to remove a file named exactly this way: t followed by an asterisk at the end.

问题是你将两个参数传递给subprocess.Popen:rm和一个路径,例如/ home / user / t *(如果prefix是t)。然后Popen将尝试删除一个名称完全相同的文件:t后面跟一个星号。

If you want to use Popen with the wildcard, you should pass the shell parameter as True. In this case, however, the command should be a string, not a list of arguments:

如果要将Popen与通配符一起使用,则应将shell参数作为True传递。但是,在这种情况下,命令应该是字符串,而不是参数列表:

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

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

(否则,参数列表将被赋予新shell,而不是命令)

Another solution, safer and more efficient, is to use the glob module:

另一个更安全,更高效的解决方案是使用glob模块:

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

All in all, however, I agree that levon solution is the saner one. In this case, glob is the answer too:

总而言之,我同意levon解决方案更为理智。在这种情况下,glob也是答案:

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

#2


14  

Would you consider this approach using os.remove() to deleting files instead of rm:

您是否会考虑使用os.remove()来删除文件而不是rm:

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

Update (basically moving my comment from below into my answer):

更新(基本上将我的评论从下面移到我的答案中):

As os.remove() can't handle wildcards on its own, using the glob module to help will yield a solution as repeated verbatim from this SO answer:

由于os.remove()无法自己处理通配符,因此使用glob模块来帮助将产生一个解决方案,如同这个SO答案一样:

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

#3


0  

I would try something like this (which also works on Windows, though I'm guessing that's not a concern for you:

我会尝试这样的东西(这也适用于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)