You can create a searchable inventory of every accessible file in a folder with the PowerShell built into Windows 10 and Windows 11. The command below records each file’s name, extension, exact size, size in MB, last-modified time, and full path, then saves the results as a CSV file that you can open and sort in Excel or another spreadsheet app. It works in Windows PowerShell 5.1, which is installed by default on Windows 10 and later Windows client releases, and also works in newer PowerShell versions.

A Windows desktop shows PowerShell creating a file inventory CSV, displayed in Excel beside File Explorer. Before you create the file inventory​

You do not need administrator rights to inventory folders your Windows account can already read. Run PowerShell normally unless you deliberately need to inspect a protected location.

Choose two locations:

  • Source folder: the folder whose files you want to list.
  • Output CSV file: where the inventory will be saved.
Warning: The CSV can expose filenames and full folder paths, which may reveal project names, account names, or other sensitive information. Store and share the CSV accordingly.
Also save the CSV outside the folder you are scanning. If you save it inside the source folder, it can become part of a later inventory and make the result confusing.

Examples:

  • Source folder: C:\Users\Taylor\Documents\Projects
  • Output CSV: C:\Users\Taylor\Desktop\Projects-FileList.csv

If either path contains spaces, keep the single quotation marks shown in the commands. PowerShell treats the quoted text as one path.

Create a complete CSV list of files and subfolders​

  1. Open PowerShell.
    • On Windows 10, select Start, type powershell, then open Windows PowerShell.
    • On Windows 11, select Start, type powershell, and open Windows PowerShell. Depending on the PC configuration, PowerShell may open in Windows Terminal instead; that is fine.
  2. Copy the following block into PowerShell.
  3. Change only the two paths at the top: $SourceFolder and $CsvFile.
    Code:
    $SourceFolder = 'C:\Users\Taylor\Documents\Projects'
    $CsvFile = 'C:\Users\Taylor\Desktop\Projects-FileList.csv'
    
    $CsvFolder = Split-Path -LiteralPath $CsvFile -Parent
    
    if (-not (Test-Path -LiteralPath $SourceFolder -PathType Container)) {
        throw "The source folder does not exist: $SourceFolder"
    }
    
    if (-not (Test-Path -LiteralPath $CsvFolder -PathType Container)) {
        throw "The folder for the CSV does not exist: $CsvFolder"
    }
    
    if (Test-Path -LiteralPath $CsvFile) {
        throw "The CSV already exists. Change the file name or move the existing file: $CsvFile"
    }
    
    $Inventory = @(
        Get-ChildItem -LiteralPath $SourceFolder -File -Recurse -Force `
            -ErrorAction SilentlyContinue -ErrorVariable ScanErrors |
        Select-Object `
            Name,
            Extension,
            @{Name='SizeBytes'; Expression={$_.Length}},
            @{Name='SizeMB'; Expression={[math]::Round($_.Length / 1MB, 2)}},
            LastWriteTime,
            FullName |
        Sort-Object FullName
    )
    
    if ($Inventory.Count -eq 0) {
        throw "No accessible files were found in: $SourceFolder"
    }
    
    $Inventory | Export-Csv -LiteralPath $CsvFile -NoTypeInformation -Encoding UTF8
    
    "Created $($Inventory.Count) file records:"
    $CsvFile
    
    if ($ScanErrors.Count -gt 0) {
        ""
        "Some items could not be read. Review the first 10 errors with:"
        '$ScanErrors | Select-Object -First 10'
    }
  4. Press Enter after pasting the full block. If PowerShell shows a continuation prompt beginning with >>, it is still waiting for an unfinished command. Press Ctrl+C, then paste the complete block again.
  5. Wait for PowerShell to display the number of file records created and the CSV path. A large folder tree, network location, or external drive can take more than a few seconds.

The resulting CSV has these columns:

ColumnWhat it contains
NameFilename, including its extension
ExtensionFile extension such as .docx, .jpg, or .pdf
SizeBytesExact file size in bytes
SizeMBFile size in megabytes, rounded to two decimal places
LastWriteTimeThe file’s last-modified date and time
FullNameComplete folder path and filename

The -Recurse parameter tells PowerShell to scan the selected folder and all subfolders. The -File parameter excludes folders from the CSV so every row represents a file. The -Force parameter includes hidden files where your account has permission to read them; it does not bypass Windows security permissions.

Verify the inventory before opening it in Excel​

First, confirm that PowerShell created a file at the output location:

Test-Path -LiteralPath $CsvFile -PathType Leaf

The expected result is:

True

Next, load the CSV back into PowerShell and count its rows:

Code:
$ImportedInventory = Import-Csv -LiteralPath $CsvFile
$ImportedInventory.Count

The returned number should match the file-record count shown when you created the inventory.

To inspect the first five entries directly in PowerShell, run:

Code:
$ImportedInventory |
    Select-Object -First 5 Name, Extension, SizeMB, LastWriteTime, FullName |
    Format-Table -AutoSize

This is only a preview. Do not add Format-Table before Export-Csv in the original inventory command. Formatting cmdlets create display-oriented output rather than the structured file objects that Export-Csv needs.

To open the CSV in its default associated application, such as Excel, run:

Invoke-Item -LiteralPath $CsvFile

You can also open File Explorer, browse to the CSV, and double-click it.

In Excel, select any cell in the list and use Data > Filter to add filter arrows to the header row. You can then sort by SizeMB, filter by an extension such as .pdf, or search the FullName column for a folder or filename fragment.

Create a quick on-screen folder list instead​

If you only need to inspect the folder contents and do not need a CSV file, use this shorter command:

Code:
Get-ChildItem -LiteralPath 'C:\Users\Taylor\Documents\Projects' -File -Recurse -Force |
    Select-Object Name, Extension, Length, LastWriteTime, FullName |
    Sort-Object FullName |
    Format-Table -AutoSize

Change the path to your own source folder. This displays files in the PowerShell window but does not save anything.

For a top-level listing only, remove -Recurse:

Code:
Get-ChildItem -LiteralPath 'C:\Users\Taylor\Documents\Projects' -File -Force |
    Select-Object Name, Extension, Length, LastWriteTime, FullName |
    Sort-Object Name |
    Format-Table -AutoSize

That version lists files directly inside the selected folder but ignores files stored in its subfolders.

Adjust the inventory for a narrower search​

For a very large folder tree, it is often better to create a targeted inventory rather than scan everything.

List only PDF files​

Replace the Get-ChildItem line in the main script with this version:

Code:
Get-ChildItem -LiteralPath $SourceFolder -File -Recurse -Force -Filter '*.pdf' `
    -ErrorAction SilentlyContinue -ErrorVariable ScanErrors |

Keep the remaining Select-Object, Sort-Object, and Export-Csv lines unchanged.

List only files modified after a specific date​

Add this line immediately after the $CsvFile line:

$ChangedAfter = Get-Date '2026-01-01'

Then add this pipeline stage between Get-ChildItem and Select-Object:

Where-Object { $_.LastWriteTime -gt $ChangedAfter } |

The relevant part of the command becomes:

Code:
Get-ChildItem -LiteralPath $SourceFolder -File -Recurse -Force `
    -ErrorAction SilentlyContinue -ErrorVariable ScanErrors |
Where-Object { $_.LastWriteTime -gt $ChangedAfter } |
Select-Object `

Use an unambiguous date format such as 2026-01-01, not a regional format such as 1/1/26.

Use your regional CSV separator​

Most Windows installations use commas in CSV files, and Excel normally opens those files correctly. If your spreadsheet program places all data into one column because it expects a semicolon or another regional list separator, change the export line to:

$Inventory | Export-Csv -LiteralPath $CsvFile -NoTypeInformation -UseCulture -Encoding UTF8

Use a new output filename or move the existing CSV first, because the script intentionally stops rather than overwriting an existing inventory.

Troubleshoot common inventory problems​

PowerShell says the source folder does not exist​

Check the value assigned to $SourceFolder:

Code:
$SourceFolder
Test-Path -LiteralPath $SourceFolder -PathType Container

The second command must return True. Confirm that the path points to a folder, not a file, and that you retained the enclosing quotation marks. A path with spaces, such as C:\Users\Taylor\OneDrive - Contoso\Documents, must remain quoted.

Use -LiteralPath as shown rather than changing it to -Path. Literal paths prevent PowerShell from treating characters such as [ and ] as wildcard patterns.

The script says the CSV already exists​

This is intentional protection against overwriting a previous inventory. Change the output filename in $CsvFile, for example:

$CsvFile = 'C:\Users\Taylor\Desktop\Projects-FileList-October.csv'

Alternatively, move the older CSV to an archive folder before running the script again.

The inventory is missing files​

The main script includes hidden files through -Force, but it cannot read locations for which your account lacks permission. It also does not use administrator privileges to override file-system security.

Check whether the scan encountered inaccessible locations:

$ScanErrors | Select-Object -First 10

If the errors identify a folder you are authorized to inspect, run PowerShell using an account that has access to that folder. Do not run PowerShell as administrator solely to inventory ordinary personal folders.

Also note that recursive enumeration does not normally follow directory symbolic links. This helps avoid unexpected loops or scanning the same redirected location repeatedly.

The CSV opens as one long column in Excel​

Create a new CSV using the -UseCulture export method shown earlier. That tells PowerShell to use the list separator configured for the current Windows regional settings.

If the file already exists, do not remove it blindly. Rename it, move it, or choose a different output name before rerunning the command.

The CSV is empty or PowerShell reports no accessible files​

Confirm that the source folder actually contains files and that you did not accidentally use the output folder as the source. For a quick visible check, run:

Get-ChildItem -LiteralPath $SourceFolder -File -Force

If that command produces no results, the folder contains no files directly inside it. Add -Recurse to check its subfolders:

Get-ChildItem -LiteralPath $SourceFolder -File -Recurse -Force

The inventory takes too long​

Scanning a large drive, a disconnected network share, a cloud-synced folder with placeholder files, or a folder containing hundreds of thousands of files can take significant time. Press Ctrl+C to stop the command; no completed CSV is guaranteed when a running export is interrupted.

For a more manageable inventory, scan a narrower source folder, omit -Recurse to exclude subfolders, or use -Filter to inventory one extension at a time.