如何在 Python 中将 mv 命令与子进程一起使用

Posted

技术标签:

【中文标题】如何在 Python 中将 mv 命令与子进程一起使用【英文标题】:How to use the mv command in Python with subprocess 【发布时间】:2014-03-15 07:46:16 【问题描述】:

我在 /home/somedir/subdir/ 中有很多文件,我正在尝试以编程方式将它们全部移动到 /home/somedir。

现在我有这个:

subprocess.call(["mv", "/home/somedir/subdir/*", "somedir/"])

但它给了我这个错误:

mv: cannot stat `/home/somedir/subdir/*': No such file or directory

我知道它确实存在,因为当我使用与脚本使用的完全相同的命令手动键入 mv 命令时,它可以完美运行。

【问题讨论】:

Calling rm from subprocess using wildcards does not remove the files 的可能重复项 它很接近,但恕我直言不是重复的,因为另一个使用的是Popen,并且有一个更复杂的例子。 嗯,问题和解决思路很接近。我已经看到一些不那么明显的接近投票...... 我认为这是一个骗局——这是相同的实际问题,具有相同的实际解决方案。这个问题是问题的一个更好的例子,但这并不意味着它是一个不同的问题。 【参考方案1】:

这是使用子进程 Popen 的一种简单方法

import subprocess
import os

class FolderCommands:
    src = None
    dst = None

    def __init__(self, src, dst):
        self.src = src
        self.dst = dst

    def move(self):
        listOfFiles = os.listdir(self.src)
        print(listOfFiles)
        modify_src = self.src.replace(" ", "\ ")
        dst = self.dst.replace(" ", "\ ")
        for f in listOfFiles:
            #Attaching the filename at the end of the src path

            fullPath = modify_src + "/'" + f +"'"
            subprocess.Popen("mv" + " " + fullPath + " " + dst, shell=True)

obj = FolderCommands(input("Enter Source path"), input("Enter Destination path"))
obj.move()

【讨论】:

虽然这确实会转义空白,但还有其他值得关注的字符。制表符、换行符和单引号都是文件名中的有效字符,需要特别注意。【参考方案2】:

如果你这样调用子进程:

subprocess.call(["mv", "/home/somedir/subdir/*", "somedir/"])

您实际上将参数/home/somedir/subdir/* 提供给mv 命令,并带有一个实际的* 文件。也就是说,您实际上是在尝试移动 * 文件。

subprocess.call("mv /home/somedir/subdir/* somedir/", shell=True)

它将使用扩展第一个参数的 shell。

注意事项:当使用 shell=True 参数时,您需要将参数列表更改为将提供给 shell 的字符串。

提示:您还可以使用 os.rename()shutil.move() 函数以及 os.path.walk()os.listdir() 以更 Pythonic 的方式将文件移动到目标。

【讨论】:

+2 用于 Pythonic 成语;否则,还不如使用外壳!【参考方案3】:

您正在使用 shell globbing *,并希望 mv 命令知道它的含义。您可以通过这种方式从命令 shell 中得到相同的错误:

$ mv 'somedir/subdir/*' ...

注意引号。 shell 通常会为您在* 上进行全局匹配,但命令不会在其命令行上执行此操作;连贝壳都没有。有一个名为 fnmatch 的 C 库函数可以为您执行 shell 样式的通配,每种编程语言都或多或少地复制了它。它甚至可能在 Python 中具有相同的名称。或者里面可能有“glob”这个词;我不记得了。

【讨论】:

您的示例确实有效,shell 在双引号内展开,您应该使用单引号来说明问题。 哦,对了。真正有趣的是 (ba)sh 处理双引号内的单引号的方式。当您将它存储在 var 中然后尝试将其拼接到命令行中时,它可能会变得非常棘手!【参考方案4】:

您可以通过添加参数shell=True 来解决此问题,以在您的情况下考虑通配符(因此直接编写命令,无需任何列表):

subprocess.call("mv /home/somedir/subdir/* somedir/", shell=True)

没有它,参数将直接赋予带有星号的mv 命令。返回与一般模式匹配的每个文件是 shell 的工作。

【讨论】:

以上是关于如何在 Python 中将 mv 命令与子进程一起使用的主要内容,如果未能解决你的问题,请参考以下文章

使用来自 Python 的 7-zip cmd 行和子进程

如何加快与子进程的通信

线程与子线程(python3入门)

python中将linux命令写在一起使用

在Python中,如何将多个进程与popen链接在一起,同时将中间部分结果重定向到一个字符串中

如何让 Python 说话