How to Clone Local Group Memberships in Batch Script
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.).
This script focuses on Local Groups on the specific machine. It does not copy Domain Security Group memberships (like "Domain Admins" or "VPN Users"), which are managed on the Domain Controller.
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.
Advise your users that "Users" is a default group for everyone. The script might show "already a member" for this group, which is normal and expected.
Best Practices for Access Management
- 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. - Audit the Change: Always output a log of exactly which groups the user was added to, so you can reverse the changes if needed.
- Local vs. Domain: Remember this only affects access to this specific computer. For file server access, you need to modify AD groups.
The net user command's column-based output is notoriously difficult to parse with only Batch. The iterative "Check all groups" method is slower but 100% reliable in pure Batch.
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.