Skip to content

How to Clone Local Group Memberships in Batch Script

Learn how to automate the replication of local group permissions from a source user to a new employee using a reliable Batch script for efficient onboarding and troubleshooting.

When a new employee joins a team, one of the most common requests is: "Can you just give them the same access as Bob?" Manually checking every local group that "Bob" is in and then adding the new user to each one is tedious and prone to error. Missing a single group can result in the new user being unable to access a file share or run a specific application. A Batch script can automate this "Cloning" process, reading the source user's memberships and applying them to the target user instantly.

This guide explains how to script this replication.

Why Clone User Access?

  • Onboarding Efficiency: Drastically reducing the time it takes to set up a new workstation for a replacement staff member.
  • Troubleshooting Access: Temporarily mirroring a user's permissions to a test account to verify if a problem is permission-related.
  • Migration: Moving a user to a new profile while ensuring they retain access to all local resources (Printers, backup operators, etc.).

Method 1: Iterating Through All Local Groups (Pure Batch)

Since net user output is multi-column and unreliable to parse, the reliable pure-Batch approach is to iterate through every local group on the system and check if the source user is a member of each.

@echo off
setlocal EnableDelayedExpansion

:: Check for admin rights
net session >nul 2>&1
if %errorlevel% neq 0 (
    echo [ERROR] Administrator privileges are required.
    pause
    exit /b 1
)

set /p "SOURCE=Source username (copy from): "
set /p "TARGET=Target username (copy to): "

if "!SOURCE!"=="" (
    echo [ERROR] No source username entered.
    pause
    exit /b 1
)
if "!TARGET!"=="" (
    echo [ERROR] No target username entered.
    pause
    exit /b 1
)

:: Verify both users exist
net user "!SOURCE!" >nul 2>&1
if !errorlevel! neq 0 (
    echo [ERROR] Source user "!SOURCE!" not found.
    pause
    exit /b 1
)
net user "!TARGET!" >nul 2>&1
if !errorlevel! neq 0 (
    echo [ERROR] Target user "!TARGET!" not found.
    pause
    exit /b 1
)

echo.
echo [PROCESS] Cloning local group memberships from "!SOURCE!" to "!TARGET!"...
echo.

set "ADDED=0"
set "SKIPPED=0"

:: Iterate through all local groups on the system
for /f "skip=4 tokens=1,* delims=*" %%a in ('net localgroup 2^>nul') do (
    :: Group names are prefixed with * in the output
    for /f "tokens=*" %%g in ("%%b") do (
        set "GRP=%%g"

        :: Check if source user is a member of this group
        net localgroup "!GRP!" 2>nul | findstr /i /c:"!SOURCE!" >nul
        if !errorlevel! equ 0 (
            :: Check if target is already a member
            net localgroup "!GRP!" 2>nul | findstr /i /c:"!TARGET!" >nul
            if !errorlevel! equ 0 (
                echo   [SKIP] "!TARGET!" is already in "!GRP!"
                set /a "SKIPPED+=1"
            ) else (
                net localgroup "!GRP!" "!TARGET!" /add >nul 2>&1
                if !errorlevel! equ 0 (
                    echo   [ADD ] Added "!TARGET!" to "!GRP!"
                    set /a "ADDED+=1"
                ) else (
                    echo   [FAIL] Could not add "!TARGET!" to "!GRP!"
                )
            )
        )
    )
)

echo.
echo [RESULT] Added to !ADDED! group(s^), skipped !SKIPPED! (already member^).
pause

Method 2: Using PowerShell (Faster and More Reliable)

For environments where PowerShell is available, this approach is significantly faster because it queries the source user's memberships directly rather than checking every group.

@echo off
setlocal EnableDelayedExpansion

echo ============================================================
echo   Local Group Membership Mirror Utility
echo ============================================================
echo.

:: Check for admin rights
net session >nul 2>&1

if !errorlevel! neq 0 (
    echo [ERROR] Administrator privileges are required. >&2
    echo.
    echo Right-click and select "Run as administrator"
    pause
    exit /b 1
)

echo [OK] Running with administrator privileges
echo.

:: Get source and target usernames
set /p "SRC=Source username (copy from): "
set /p "DST=Target username (copy to): "

echo.

if "!SRC!"=="" (
    echo [ERROR] No source username entered.
    pause
    exit /b 1
)

if "!DST!"=="" (
    echo [ERROR] No target username entered.
    pause
    exit /b 1
)

if /i "!SRC!"=="!DST!" (
    echo [ERROR] Source and target usernames cannot be the same.
    pause
    exit /b 1
)

echo ============================================================
echo   Configuration
echo ============================================================
echo.
echo   Source User: !SRC!
echo   Target User: !DST!
echo.
echo ============================================================
echo.

echo [PROCESS] Mirroring local group memberships from "!SRC!" to "!DST!"...
echo.

:: Create PowerShell script for better readability
set "PSScript=%TEMP%\mirror_groups_%RANDOM%.ps1"

(
echo:
echo Write-Host ""
echo Write-Host "Scanning group memberships..." -ForegroundColor Cyan
echo Write-Host ""
echo:
echo # Get groups the source user is a member of
echo $added = 0
echo $skipped = 0
echo $failed = 0
echo:
echo # Query WMI for group memberships
echo $groups = Get-WmiObject Win32_GroupUser ^| Where-Object {
echo     $_.PartComponent -match "Name=`"!SRC!`""
echo }
echo:
echo if (-not $groups^) {
echo     Write-Host "[INFO] Source user '!SRC!' is not a member of any local groups" -ForegroundColor Yellow
echo     exit 0
echo }
echo:
echo Write-Host "Source user is member of $(@($groups).Count) group(s):" -ForegroundColor Cyan
echo Write-Host ""
echo:
echo foreach ($g in $groups^) {
echo     # Extract group name from WMI object
echo     if ($g.GroupComponent -match 'Name="([^"]+^)"') {
echo         $groupName = $matches[1]
echo:
echo         # Skip built-in system groups that shouldn't be modified
echo         if ($groupName -in @('None', 'Domain Users', 'Domain Admins'^)^) {
echo             Write-Host "  [SKIP] Skipping system group: $groupName" -ForegroundColor Gray
echo             continue
echo         }
echo:
echo         # Check if target user is already in this group
echo         $members = net localgroup "$groupName" 2^>$null
echo         $isMember = $false
echo         foreach ($line in $members^) {
echo             if ($line.Trim(^) -ieq "!DST!"^) { $isMember = $true; break }
echo         }
echo:
echo         if ($isMember^) {
echo             Write-Host "  [SKIP] '!DST!' already in '$groupName'" -ForegroundColor Yellow
echo             $skipped++
echo         } else {
echo             # Add target user to group
echo             Write-Host "  [ADD]  Adding '!DST!' to '$groupName'..." -NoNewline
echo:
echo             $result = net localgroup "$groupName" "!DST!" /add 2^>^&1
echo:
echo             if ($LASTEXITCODE -eq 0^) {
echo                 Write-Host " OK" -ForegroundColor Green
echo                 $added++
echo             } else {
echo                 Write-Host " FAILED" -ForegroundColor Red
echo                 Write-Host "         Error: $result" -ForegroundColor Red
echo                 $failed++
echo             }
echo         }
echo     }
echo }
echo:
echo Write-Host ""
echo Write-Host "============================================================" -ForegroundColor Cyan
echo Write-Host "  Summary" -ForegroundColor Cyan
echo Write-Host "============================================================" -ForegroundColor Cyan
echo Write-Host ""
echo Write-Host "  Groups added:      $added" -ForegroundColor White
echo Write-Host "  Already member:    $skipped" -ForegroundColor White
echo Write-Host "  Failed:            $failed" -ForegroundColor White
echo Write-Host ""
echo:
echo if ($added -gt 0^) {
echo     Write-Host "[SUCCESS] Group memberships mirrored successfully" -ForegroundColor Green
echo } elseif ($skipped -gt 0 -and $failed -eq 0^) {
echo     Write-Host "[INFO] Target user already has all group memberships" -ForegroundColor Cyan
echo } elseif ($failed -gt 0^) {
echo     Write-Host "[WARNING] Some groups could not be added" -ForegroundColor Yellow
echo }
) > "%PSScript%"

:: Execute PowerShell script
powershell -NoProfile -ExecutionPolicy Bypass -File "%PSScript%"

set "Result=!errorlevel!"

:: Cleanup
del "%PSScript%" >nul 2>&1

echo.
echo ============================================================
echo.

pause
endlocal
exit /b !Result!

Creating a Group Membership Cloning Tool

This professional script combines both approaches with a safety confirmation and detailed logging.

@echo off
setlocal EnableDelayedExpansion

echo ============================================================
echo   Access Right Cloning Tool
echo ============================================================

:: 1. Check for admin rights
net session >nul 2>&1
if %errorlevel% neq 0 (
    echo [ERROR] Administrator privileges are required.
    pause
    exit /b 1
)

:: 2. Get inputs
set /p "SRC=Source Username (copy FROM): "
set /p "DST=Target Username (copy TO): "

if "!SRC!"=="" (
    echo [ERROR] No source username entered.
    pause
    exit /b 1
)
if "!DST!"=="" (
    echo [ERROR] No target username entered.
    pause
    exit /b 1
)

:: 3. Verify both users exist
net user "!SRC!" >nul 2>&1
if !errorlevel! neq 0 (
    echo [ERROR] Source user "!SRC!" not found.
    pause
    exit /b 1
)
net user "!DST!" >nul 2>&1
if !errorlevel! neq 0 (
    echo [ERROR] Target user "!DST!" not found.
    pause
    exit /b 1
)

:: 4. Show source user's current memberships
echo.
echo [INFO] "!SRC!" is a member of these local groups:
echo   -----------------------------------------
for /f "skip=4 tokens=1,* delims=*" %%a in ('net localgroup 2^>nul') do (
    for /f "tokens=*" %%g in ("%%b") do (
        net localgroup "%%g" 2>nul | findstr /i /c:"!SRC!" >nul
        if !errorlevel! equ 0 echo   %%g
    )
)
echo   -----------------------------------------

:: 5. Confirm
echo.
set /p "CONFIRM=Clone these memberships to "!DST!"? (Y/N): "
if /i not "!CONFIRM!"=="Y" (
    echo [INFO] Cancelled. No changes made.
    pause
    exit /b 0
)

:: 6. Perform the cloning
echo.
echo [PROCESS] Cloning memberships...
echo.

set "ADDED=0"
set "SKIPPED=0"
set "FAILED=0"

for /f "skip=4 tokens=1,* delims=*" %%a in ('net localgroup 2^>nul') do (
    for /f "tokens=*" %%g in ("%%b") do (
        net localgroup "%%g" 2>nul | findstr /i /c:"!SRC!" >nul
        if !errorlevel! equ 0 (
            net localgroup "%%g" 2>nul | findstr /i /c:"!DST!" >nul
            if !errorlevel! equ 0 (
                set /a "SKIPPED+=1"
            ) else (
                net localgroup "%%g" "!DST!" /add >nul 2>&1
                if !errorlevel! equ 0 (
                    echo   [ADD ] "%%g"
                    set /a "ADDED+=1"
                ) else (
                    echo   [FAIL] "%%g"
                    set /a "FAILED+=1"
                )
            )
        )
    )
)

:: 7. Summary
echo.
echo [SUMMARY] Added: !ADDED!  |  Skipped: !SKIPPED!  |  Failed: !FAILED!

echo ============================================================
pause

Common Pitfalls and How to Avoid Them

Administrator Rights

You must run as Administrator. Standard users cannot add anyone to groups.

Built-in Groups

Be careful when cloning memberships of highly privileged accounts. You might accidentally add a temporary contractor to "Administrators" or "Backup Operators" if you clone the wrong template user.

Best Practices for Access Management

  1. Use Role-Based Templates: Create "Template Accounts" (e.g., _Template_Dev, _Template_HR) that are disabled but configured with the perfect group memberships. Clone from these rather than from random active users.
  2. Audit the Change: Always output a log of exactly which groups the user was added to, so you can reverse the changes if needed.
  3. Local vs. Domain: Remember this only affects access to this specific computer. For file server access, you need to modify AD groups.

Conclusion

Cloning local group memberships via Batch script is a powerful time-saving technique for system administrators. By automating the replication of access rights, you ensure consistency across your team, eliminate human error in provisioning, and dramatically speed up the onboarding process. This professional capability allows you to maintain a secure and well-structured permission model, ensuring that every user has exactly the access they need, no more, no less.

Navigation