PowerShell · 26.09.2025

Резервный профиль

Сегодня для пятничных посиделок предлагаю взглянуть на PS1-скрипт резервирования файлов профиля пользователя.

Скрипт отлично зарекомендовал себя и как автономный метод резервного копирования файлов из профиля пользователя, так и в виде назначенного задания по срабатыванию определённого триггера.

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

А ещё у скрипта есть прогресс-бар, но это уже детали…

# Заголовок консоли скрипта #
[System.Console]::Title = "Копирование профиля текущего пользователя"

# Укажите путь к профилю пользователя #
$sourcePath = "$env:USERPROFILE"

# Укажите путь к целевой папке с именем пользователя #
$destinationPath = "\\192.168.1.1\userprofiles\$($env:USERNAME)"

# Определяем массив папок, которые нужно скопировать #
$foldersToCopy = @( "Desktop", "Documents", "Downloads", "Pictures", "Music" )

# Создаем целевую папку, если она не существует #
if (!(Test-Path -Path $destinationPath))
{
    New-Item -ItemType Directory -Path $destinationPath
}

# Общая информация для прогресса #
$totalFolders = $foldersToCopy.Count
$currentFolderIndex = 0

# Копирование файлов #
foreach ($folder in $foldersToCopy) 
{
    $currentFolderIndex++
    $sourceFolder = Join-Path -Path $sourcePath -ChildPath $folder
    $targetFolder = Join-Path -Path $destinationPath -ChildPath $folder
    
    # Устанавливаем заголовок прогресса #
    $progressMessage = "Копирование $folder"
    
    # Отображаем прогресс #
    Write-Progress -Activity "Копирование папок" -Status $progressMessage -PercentComplete (($currentFolderIndex / $totalFolders) * 100)

    # Копируем папку, если она существует #
    if (Test-Path -Path $sourceFolder) 
    {
        # Создаем целевую папку, если она не существует #
        if (!(Test-Path -Path $targetFolder)) 
        { New-Item -ItemType Directory -Path $targetFolder }
        
        # Получаем файлы для копирования, исключая desktop.ini и thumbs.db #
        $filesToCopy = Get-ChildItem -Path $sourceFolder -Recurse | Where-Object { $_.Name -ne 'desktop.ini' -and $_.Name -ne 'thumbs.db' }
        
        # Копируем файлы #
        $totalFiles = $filesToCopy.Count
        $currentFileIndex = 0
        
        foreach ($file in $filesToCopy) 
        {
            $currentFileIndex++
            $destinationFile = Join-Path -Path $targetFolder -ChildPath $file.FullName.Substring($sourceFolder.Length + 1)
            $destinationFileDir = Split-Path -Path $destinationFile -Parent
            
            # Создаем директорию файла, если она не существует #
            if (!(Test-Path -Path $destinationFileDir)) 
            { New-Item -ItemType Directory -Path $destinationFileDir -Force }

            # Копируем файл #
            Copy-Item -Path $file.FullName -Destination $destinationFile -Force
            
            # Отображаем прогресс по файлам #
            Write-Progress -Activity "Копирование файлов" -Status "Копирование $($file.Name)" -PercentComplete (($currentFileIndex / $totalFiles) * 100)
        }
    }
}

# Завершение копирования #
Write-Progress -Activity "Копирование папок" -Status "Завершено!" -Completed

Нужно только актуализировать $destinationPath не затрагивая переменную с именем пользователя. И, само собой, нужно обеспечить постоянную доступность сетевого пути.

У скрипта есть один, но существенный минус — не предусмотрено хранение истории версий файлов, но эта тема уже скорее не про скрипты…