Шутил пытается скопировать несуществующие каталоги - PullRequest
0 голосов
/ 28 октября 2019

Я пытаюсь скопировать папку «Документы» в профиле пользователя Windows, shutil.copytree(documents, destination) работает частично. Он скопирует документы в корневой каталог назначения, в данном случае на диск R:, и попытается скопировать другие специальные папки Windows («Моя музыка», «Мои рисунки» и т. Д.), Даже если они несуществует в Документах.

import shutil


def main():

   try:

       user_profile = os.getenv("USERPROFILE")

       # Construct a full path to the documents folder 
       documents = Path(user_profile).joinpath("Documents")

       # Destination for the Documents folder
       destination = Path("R:\\Test")

       shutil.copytree(documents, destination)            

   except (FileNotFoundError, shutil.Error) as error:
       print(error)


if __name__ == '__main__':
    main()

Это отрывок исключения, которое выдается:

[('C:\\Users\\ConsoleGeek\\Documents\\My Music', 'R:\\Test\\My Music', 
"[WinError 5] Access is denied: 'C:\\\\Users\\\\ConsoleGeek\\\\Documents\\\\My Music'")
...

Ни одна из этих папок не существует в Документах, поэтому я не до конца понимаю, почему shutil пытаетсяскопируйте эти специальные папки. Если я пытаюсь скопировать обычную папку под профилем пользователя, это работает.

Ответы [ 2 ]

0 голосов
/ 29 октября 2019

Чтобы понять, почему copytree() пытается скопировать специальные папки при попытке скопировать Documents, нам нужно сначала взглянуть на скрытые файлы.

Используя cmd.exe:

Если мы откроем cmd.exe и изменим каталог на Documents, мы можем запустить dir /A:H /Bчтобы увидеть все папки (в том числе скрытые).

C:\Users\ConsoleGeek\Documents>dir /A:H /B
desktop.ini
My Music
My Pictures
My Videos

Использование Powershell :

Если мы откроем powershell.exe и введем Get-ChildItem -Force -File -Path .\Documents\, в нем будут перечислены все элементы вDocuments папка.

Примечание : специальные папки не отображаются.

PS C:\Users\ConsoleGeek> Get-ChildItem -Force -File -Path .\Documents\


    Directory: C:\Users\ConsoleGeek\Documents


Mode                LastWriteTime         Length Name
----                -------------         ------ ----
-a-hs-        10/4/2019   6:00 PM            402 desktop.ini

Использование Python :

Я запустил следующий код в VSCode:

def main():

    try:
        user_profile = os.getenv("USERPROFILE")
        documents = Path(user_profile).joinpath("Documents")

        for item in documents.iterdir():
            print(item)

    except (FileNotFoundError, shutil.Error) as error:
       print(error)

if __name__ == '__main__':
    main()


# Output:
C:\Users\ConsoleGeek\Documents\desktop.ini
C:\Users\ConsoleGeek\Documents\My Music
C:\Users\ConsoleGeek\Documents\My Pictures
C:\Users\ConsoleGeek\Documents\My Videos

Использование проводника :

Если я выбрал параметр отображения скрытых файлов, папка Documents по-прежнему пуста.

Рекурсивное копирование :

Использование cmd.exe :

Использование команды xcopy с /E *Переключатели 1061 * позволяют копировать все папки / файлы, включая пустые и скрытые.

C:\Users\ConsoleGeek>xcopy Documents R:\Sync\Documents /E /H
Documents\desktop.ini
Access denied
Unable to create directory - R:\Sync\Documents\My Music
1 File(s) copied

1 File(s) copied вводит в заблуждение, поскольку при включении функции Показать скрытые файлы вы можете убедиться, что ничего не копируется.

Использование Powershell :

Используя командлет Copy-Item с переключателем -Recurse, мы получаем ошибку отказа в доступе, аналогичную cmd.exe.

Это выдержка из сообщения об ошибке.

Copy-Item : Access to the path 'C:\Users\ConsoleGeek\Documents\My Music' is denied.

Решения :

Использование cmd.exe :

xcopy имеет параметр /Exclude:filename.txt. Вы предоставляете файл с именами папок / файлов, которые хотите исключить.

My Music
My Pictures
My Video
desktop.ini

, и используете его с командой xcopy:

C:\Users\ConsoleGeek>xcopy Documents R:\Sync\Documents /E /H /EXCLUDE:filenames.txt

Использование Powershell :

Параметр -Exclude не работает с параметром -Recurse, поэтому он просто скопирует пустые папки My Music, My .... Чтобы исключить их из копируемого, вы можете предоставить подстановочный знак для параметра -Exclude.

Copy-Item -Path .\Documents\ -Destination "R:\Sync\Documents" -Exclude ("My*", ".ini")

Если вам нужно скопировать подкаталоги, но исключить некоторые, вы можете создать список каталогов, которые вы наделилине хотите скопировать и пройтись по папке Documents и проверить каждый элемент в списке. Возможно, вам придется поэкспериментировать, чтобы увидеть, что соответствует вашим требованиям.

Использование Python :

В зависимости от требований ваш скрипт, очевидно, будет немного отличаться, но вы можете использовать эту функцию для фильтрации специальных папок, и .ini файл.

import os
from pathlib import Path
import shutil
from typing import Tuple
from shutil import copytree, ignore_patterns


def copy_documents_folder(source: Path, destination: Path, ext_to_ignore: Tuple):
    copytree(source, destination, ignore = ignore_patterns(*ext_to_ignore))

def main():

   try:

       user_profile = os.getenv("USERPROFILE")
       documents = Path(user_profile).joinpath("Documents")
       destination = Path("R:\\Sync\\Documents")

       copy_documents_folder(source=documents, destination=destination, 
       ext_to_ignore=("*.ini", "My *"))


   except (FileNotFoundError, shutil.Error) as error:
       print(error)


if __name__ == '__main__':
    main()
0 голосов
/ 29 октября 2019

Я недостаточно хорошо знаю систему Windows, но вы можете попробовать позвонить

shutil.copytree(documents, destination, symlinks=True)

, если эти «специальные папки» являются символическими ссылками (или эквивалентом символических ссылок в Windows).

...