A PowerShell script for manually triggered file transfer between two SharePoint document libraries across different tenants - including guest/external access scenarios.
A single or a limited set of users from your organization have been granted guest access to the other's organization SharePoint Site. Work is delegated within your organization across users and/or departments. The script enables your organization to perform automated partial submissions, by mirroring your SharePoint site you have set up for the project.
- Connects to a source SharePoint site (own tenant) and a destination SharePoint site (external/customer tenant where the user has guest contributor access)
- Performs a differential sync: only files that are new or modified since the last run are transferred - unchanged files are skipped
- Preserves subfolder structure
- Generates a per-session transfer report (plain text, suitable for client handover) saved next to the script files
- Maintains a cumulative debug log in
%TEMP%for troubleshooting
- Windows with Windows PowerShell 5.1 (built-in, no install needed)
- PnP.PowerShell 1.12.0 - install once with:
Install-Module PnP.PowerShell -RequiredVersion 1.12.0 -Scope CurrentUser -Force
Version 1.12.0 specifically is required - newer versions (2.x, 3.x) require PowerShell 7 and will not be found by Windows PowerShell 5.1.
- Contributor access on the destination SharePoint site (guest/external invitation is sufficient)
- No admin rights needed for either installation or execution
| File | Purpose |
|---|---|
sp-transfer.ps1 |
Main script |
sp-transfer.bat |
Launcher - double-click this to run |
sp-transfer-config.ps1 |
Your configuration (never overwritten by upgrades) |
sp-upgrade.ps1 |
Self-updater - downloads latest scripts from GitHub |
All files must be kept in the same folder.
Edit sp-transfer-config.ps1 (created on first download, never overwritten by upgrades):
$site1Url = "https://yourcompany.sharepoint.com/sites/Site1"
$site2Url = "https://customertenant.sharepoint.com/sites/Site2"
$site1Library = "Documents" # Display name of the library on Site1
$site2Library = "Documents" # Display name of the library on Site2Library names must match the display name as shown in SharePoint, not the URL segment. Run
Get-PnPList | Select-Object Title, RootFolderagainst the site to confirm the correct name.
- Double-click
sp-transfer.bat - Select mode:
- 1 - Sync new files only (skip files that already exist on Site2, even if updated)
- 2 - Normal sync (new and updated files)
- 3 - Dry run (preview only)
- 4 - Upgrade
- Log in to Site1 in the browser window that opens
- Log in to Site2 in the second browser window (same account, guest access)
- Wait for the transfer to complete (or preview to finish)
- Press Enter to close - the report is saved automatically
Transfers only files that do not yet exist on Site2 (matched by relative path). Files that exist on Site2 are skipped regardless of whether the source copy is newer. Useful when you want to seed the destination with new additions without touching files that may have been edited downstream.
# Via the bat launcher: select option 1
sp-transfer.bat
# Or directly:
.\sp-transfer.ps1 -NewOnlyThe report is clearly marked [NEW FILES ONLY].
Dry run connects to both sites, compares files, and shows exactly what would be transferred - without downloading or uploading anything. Useful for verifying the diff before committing to a transfer.
# Via the bat launcher: select option 3
sp-transfer.bat
# Or directly:
.\sp-transfer.ps1 -DryRunThe dry-run report is clearly marked [DRY RUN] and lists all files that would be transferred with their [NEW] or [UPDATED] status.
Select option 4 from the bat menu (or run sp-upgrade.ps1 directly). This downloads the latest sp-transfer.ps1, sp-transfer.bat, and sp-upgrade.ps1 from GitHub. Your configuration in sp-transfer-config.ps1 is never modified. A .bak backup of each file is created before overwriting.
Each run produces a timestamped report file in the same folder as the script:
TransferReport_2024-03-24_143210.txt
Example content:
SharePoint Transfer Report
==========================
Date/Time : 2024-03-24 14:32:10
Operator : firstname.lastname
Files transferred (3)
----------------------------------------
[NEW] Data/survey_results.csv
[UPDATED] Reports/Q1_2024.xlsx
[UPDATED] Reports/Q2_2024.xlsx
Files skipped -- already up to date : 847
Failed (0)
----------------------------------------
(none)
Uses -UseWebLogin (interactive browser popup) for both connections. This handles MFA and cross-tenant guest authentication without requiring app registrations or certificates. Tokens are not cached between runs - the user logs in fresh each time.
| File | Content |
|---|---|
TransferReport_<timestamp>.txt |
Per-session delivery record, saved next to the script |
%TEMP%\SPTransfer_debug.txt |
Cumulative debug log across all sessions, for IT troubleshooting |
- Files are transferred one at a time: downloaded to a local temp folder, uploaded to Site2, then the local copy is deleted immediately. Peak local disk usage is one file at a time.
- The script is safe to run multiple times -
Add-PnPFileoverwrites the destination if the source is newer. - The update warning (
A newer version of PnP PowerShell is available) that appears on connect is harmless and can be ignored.