Python moving files and directories from one folder to another

前端 未结 4 1645
别跟我提以往
别跟我提以往 2021-01-06 11:22

I would like to move in python files and directories in one directory to another directory with overwrite ability.

I started with the following code:



        
4条回答
  •  被撕碎了的回忆
    2021-01-06 12:17

    The reason this fails:

    for dirs,files in os.listdir(path):
    

    … is that os.listdir just returns a list of filenames. So, each element is a string, and you're trying to unpack that string into two variables. Compare this:

    a, b = (1, 2, 3, 4, 5, 6, 7, 8)
    for a, b in [(1, 2, 3, 4, 5, 6, 7, 8), (9, 10)]
    dirs, files = "spam.txt"
    for dirs, files in ["spam.txt", "eggs.dat"]
    

    It's the exact same error in every case—you can't fit 8 things into 2 variables.

    Meanwhile, if listdir is just returning filenames, how do you know ones are the names of regular files, are which are the names of directories? You have to ask—e.g., by using isdir.

    So:

    for filename in os.listdir(path):
        if os.path.isdir(filename):
            # do directory stuff
        else:
            # do regular file stuff
    

    (But note that this can still be confusing if you have symlinks…)


    Meanwhile, what does "do regular file stuff" mean?

    Well, assuming you don't have a directory (or a symlink to a directory) with the same name as the file you're trying to move there, as the docs for shutil.move say, os.rename or shutil.copy2 will be used. If you're not on Windows, this is perfect—if you have permission to overwrite the target you will, otherwise you'll get a permissions error. But if you are on Windows, os.rename will fail if the target already exists.

    If you're on 3.3 or later, you can solve this by copying the shutil.move source* and using os.replace instead, as the rename docs imply. Otherwise, you will have to delete the target before renaming the source.

    * Some stdlib modules—including shutil—are meant to serve as sample code as well as usable helpers. In those cases, at the top of the module's docs, there will be a Source code: link.


    And what about "do directory stuff"? Well, if you move a directory spam to a target eggs/spam, and eggs/spam already exists as a directory, you're going to end up moving to eggs/spam/spam.

    This shouldn't be surprising, as it's exactly the same thing mv on Unix and move on Windows do, which is what shutil is trying to simulate.

    So, what you need to do here is delete the target (this time using shutil.rmtree) before moving the source.


    Which means the simplest thing to do may be to not distinguish files and directories, Windows and Unix, or anything else; just do this:

    for filename in os.listdir(path):
        target = os.path.join(compteurfolder, filename)
        try:
            shutil.rmtree(target)
        except NotADirectoryError:
            try:
                os.unlink(target)
            except FileNotFoundError:
                pass
        shutil.move(os.path.join(path, filename), target)
    

提交回复
热议问题