Purge-AzFileShare.ps1
Deletes files older than N days (optionally within a specific sub-folder) from an Azure File Share.
| Feature | |
|---|---|
| 🚀 | Scales to tens of millions of objects – streams 5 000 entries/page & handles continuation tokens |
| 🌳 | Recursive by default; optionally start lower via -StartPath |
| ⚡ | Parallel deletes (configurable) for high throughput |
| 🔍 | -WhatIf mode prints paths without deleting |
| ♻️ | Resume-safe – rerun any time; already-deleted files are skipped |
| 🔐 | Works with Shared Key or Azure AD / Managed Identity authentication |
┌──────────────┐ ┌──────────────────┐ ┌───────────────┐
│ Authenticate │────▶│ Recursive walk │────▶│ Delete / log │
└──────────────┘ └──────────────────┘ └───────────────┘
- Authenticate — reads
AZURE_STORAGE_KEYfrom the environment, or auto-retrieves it viaaz storage account keys list. - Walk — recursively lists every directory in the share (or below
-StartPath) in pages of-PageSizeentries, following continuation tokens until every file has been visited. - Filter — each file's
lastModifiedtimestamp is compared against the cut-off date (now − Days). - Delete or preview — matched files are either printed (
-WhatIf) or dispatched for deletion through a semaphore-bounded thread pool (-MaxConcurrentworkers). - Summarise — after all tasks complete, a final count of matched / deleted files is printed.
| Requirement | Notes |
|---|---|
| PowerShell 7+ | Windows · macOS · Linux · Azure Cloud Shell |
| Azure CLI 2.60+ | Script shells out to az storage file … |
| List / Delete permission | Either: • Shared Key • or Azure roles: Storage File Data SMB Share Contributor Storage File Data Privileged Contributor |
az login
az account set --subscription "<SUBSCRIPTION-GUID>"
az storage account keys list \
--resource-group <RESOURCE-GROUP> \
--account-name <STORAGE-ACCOUNT> \
--query "[0].value" -o tsvCopy the 88-character string.
export AZURE_STORAGE_ACCOUNT=<STORAGE-ACCOUNT>
export AZURE_STORAGE_KEY=<PASTE-KEY-HERE>
# PowerShell users:
# $env:AZURE_STORAGE_ACCOUNT = '<STORAGE-ACCOUNT>'
# $env:AZURE_STORAGE_KEY = '<PASTE-KEY-HERE>'./Purge-AzFileShare.ps1 `
-ResourceGroupName <RESOURCE-GROUP> `
-StorageAccountName $Env:AZURE_STORAGE_ACCOUNT `
-ShareName <FILE-SHARE> `
-Days 45 `
-StartPath '' # or 'Folder/SubFolder' to scope lower
-WhatIf # preview onlyRemove -WhatIf once the preview looks correct.
Starting purge for //myaccount/myshare | Older than 45 days (cut-off 2025-04-01 00:00:00)
logs/2025-01/app.log [WOULD be deleted]
logs/2025-02/app.log [WOULD be deleted]
logs/2025-03/app.log [WOULD be deleted]
backups/2025-02-14/db.bak [WOULD be deleted]
backups/2025-03-01/db.bak [WOULD be deleted]
----------
Matched : 5
Deleted : 0
NOTE: -WhatIf used – no files actually removed.
Once you remove -WhatIf, the script deletes the matched files in parallel
and the Deleted counter will reflect the actual removals.
| Parameter | Required | Default | Description |
|---|---|---|---|
-ResourceGroupName |
✔ | — | Resource group that owns the storage account |
-StorageAccountName |
✔ | — | Storage account hosting the share |
-ShareName |
✔ | — | File-share to purge |
-Days |
30 |
Delete files older than N days | |
-PageSize |
5000 |
Objects per list page (service max) | |
-MaxConcurrent |
32 |
Parallel delete workers | |
-StartPath |
'' |
Folder to begin recursion (blank = root) | |
-WhatIf |
— | Dry-run; no deletes executed |
| Platform | How to wire it |
|---|---|
| Azure Automation | Import as PS 7 runbook → store key in secure variables → schedule 03:00 UTC daily |
| GitHub Actions | Save key in Secrets → CRON 0 3 * * * → pwsh ./Purge-AzFileShare.ps1 … |
| Task Scheduler | pwsh -File Purge-AzFileShare.ps1 … with nightly trigger; load env vars in wrapper .bat |
PRs welcome! Ideas:
- Retry / back-off logic
- Exclusion patterns / globbing
- Output to CSV or Log Analytics
This project is licensed under the terms of the MIT license. See the LICENSE file for details.