【问题标题】:rm all files under a directory using python subprocess.call使用 python subprocess.call rm 目录下的所有文件
【发布时间】:2015-08-13 00:58:53
【问题描述】:

我正在编写一个脚本,它将文件移动到用户主文件夹中的 .trash 目录中。我想通过使用 python 的 subprocess.call() 调用 rm -rf /home/user/.trash/* 添加清空垃圾目录的功能

~$ touch file1
~$ trash file1
['mv', 'file1', '/home/rodney/.trash/']
~$ ls .trash
file1
~$ trash --empty
['rm', '-rf', '/home/rodney/.trash/*']
~$ ls .trash
file1

如您所见,rm 命令并未删除垃圾箱中的内容。但是,如果我直接在命令行上执行命令,它就可以工作。

~$ rm -rf /home/rodney/.trash/*
~$ ls .trash
~$ 

输出来自以下代码

print(cmd)
subprocess.call(cmd)

奇怪的是,如果我从 cmd 列表的最后一个参数中排除 *,那么子进程调用会起作用,但也会删除整个 .trash 目录。我不想删除 .trash 目录;只有它下面的所有东西。

总结问题

这行得通

import subprocess
subprocess.call(['rm', '-rf', '/home/rodney/.trash/'])

这不是

import subprocess
subprocess.call(['rm', '-rf', '/home/rodney/.trash/*'])

为什么?

【问题讨论】:

  • 你为什么要找rm做一些简单的事情,比如在python中删除文件?
  • 我认为写起来比创建文件列表和遍历所有子目录要快。
  • 也许吧,但从长远来看,学习 Python 必须提供的 API 会让您受益更多。见my answer。否则,您不妨将其编写为 Bash 脚本。
  • 请注意,* 不会匹配以点开头的文件。

标签: python python-3.x subprocess python-3.4 rm


【解决方案1】:

不要掏空。

这使用glob.glob() 标识要删除的文件,并使用shutil.rmtree() 删除子目录。

#!/usr/bin/env python
import os, os.path
import glob
import shutil

def remove_thing(path):
    if os.path.isdir(path):
        shutil.rmtree(path)
    else:
        os.remove(path)

def empty_directory(path):
    for i in glob.glob(os.path.join(path, '*')):
        remove_thing(i)

empty_directory('trash')

示例:

$ tree trash/
trash/
├── aaa
├── bbb
├── ccc
├── ddd
└── sub
    ├── iii
    └── jjj

1 directory, 6 files

$ ./go.py 

$ tree trash/
trash/

0 directories, 0 files

【讨论】:

  • 使用os.path.join(path, '*') 而不是path + '/*'。虽然os.listdir(path) 可能比glob 更好地表达OP 的intent(包括.* 条目)。
  • 没想到这么简单。我继续执行您的建议。我不知道* 与隐藏文件不匹配,所以我也包含了@J.F.Sebastian 的建议。对于empty_directory,我有[remove(os.path.join(path, f)) for f in os.listdir(path)],现在一切正常。
  • 请不要“仅仅因为”就使用列表推导——一个普通的for 循环在这里是 Pythonic。您无缘无故地为每次调用remove 创建listNone
  • 虽然对rm 进行炮击或使用列表推导都不会损害您的代码性能,但在您编写代码时考虑其后果是一个非常好的主意正在学习。
【解决方案2】:

Shell 将* 扩展为文件名。您需要传递 shell=True 关键字参数,以便 shell 解释 *

import subprocess
subprocess.call('rm -rf /home/rodney/.trash/*', shell=True)

根据subprocess - Frequently Used Arguments

如果shell为True,指定的命令将通过 贝壳。如果您主要将 Python 用于 它在大多数系统外壳上提供的增强控制流,并且仍然需要 方便访问其他外壳功能,例如外壳管道, 文件名通配符、环境变量扩展、~的扩展 到用户的主目录。但是,请注意 Python 本身提供 许多类似 shell 的功能的实现(特别是 glob, fnmatch、os.walk()、os.path.expandvars()、os.path.expanduser() 和 关闭)。

【讨论】:

  • 刚试过这个,如果我使用列表,现在我得到'rm:缺少操作数'。加入列表设法解决了这个问题。谢谢。
  • @Rodneyxr,我相应地更改了代码。感谢您的反馈。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-10
  • 2016-10-20
  • 1970-01-01
相关资源
最近更新 更多