How to Get the File System Type of a Drive in Batch Script
Not all drives use the same file system. NTFS supports large files, security permissions, and encryption. FAT32 is universally compatible but has a 4 GB file size limit. exFAT bridges the gap for external media. ReFS is used for resilient server storage. Before you can copy a large backup file, format a USB stick, or deploy an application, you need to know which file system the target drive is using. A Batch script can instantly identify the file system type of any connected volume, preventing compatibility failures before they happen.
This guide will explain how to audit drive file systems programmatically.
File System Comparison
Understanding the capabilities and limitations of each file system is essential for choosing the right one and predicting compatibility issues:
| File System | Max File Size | Max Volume Size | Permissions | Journaling | Best For |
|---|---|---|---|---|---|
| NTFS | 16 TB (practical) | 256 TB | Full ACLs | Yes | Internal Windows drives |
| FAT32 | 4 GB | 2 TB (32 GB Windows format limit) | None | No | Small USB drives, legacy devices |
| exFAT | 16 EB (theoretical) | 128 PB | None | No (optional in newer versions) | Large USB drives, SD cards, cross-platform |
| ReFS | 35 PB | 35 PB | Full ACLs | Yes (metadata) | Windows Server storage spaces |
The 4 GB FAT32 limit is the most common source of file copy failures. Copying a 5 GB video file or a large database backup to a FAT32 drive fails silently or with a misleading "not enough space" error, even when the drive has plenty of free space.
Method 1: Comprehensive Drive Inventory
This method displays all connected volumes with their file system type, drive letter, size, free space, and health status.
Implementation
@echo off
setlocal
echo [INFO] Drive file system inventory:
echo --------------------------------------------------
powershell -NoProfile -Command ^
"$volumes = Get-Volume -ErrorAction SilentlyContinue |" ^
" Where-Object { $_.DriveLetter -and $_.FileSystemType };" ^
"if (-not $volumes) {" ^
" Write-Host 'No volumes with drive letters found.';" ^
" exit 0" ^
"};" ^
"$volumes | ForEach-Object {" ^
" $totalGB = [math]::Round($_.Size / 1GB, 1);" ^
" $freeGB = [math]::Round($_.SizeRemaining / 1GB, 1);" ^
" $usedPct = if ($_.Size -gt 0) { [math]::Round((1 - $_.SizeRemaining / $_.Size) * 100) } else { 0 };" ^
" [PSCustomObject]@{" ^
" Drive = \"$($_.DriveLetter):\";" ^
" FileSystem = [string]$_.FileSystemType;" ^
" Label = if ($_.FileSystemLabel) { $_.FileSystemLabel } else { '(none)' };" ^
" 'Total GB' = $totalGB;" ^
" 'Free GB' = $freeGB;" ^
" 'Used %%' = $usedPct;" ^
" Health = [string]$_.HealthStatus" ^
" }" ^
"} | Format-Table -AutoSize"
echo --------------------------------------------------
endlocal
exit /b 0
Sample output:
Drive FileSystem Label Total GB Free GB Used % Health
----- ---------- ----- -------- ------- ------ ------
C: NTFS Windows 476.9 234.1 51 Healthy
D: NTFS Data 931.5 612.3 34 Healthy
E: exFAT BACKUP_USB 119.2 87.4 27 Healthy
F: FAT32 CAMERA_SD 29.7 15.2 49 Healthy
Why Get-Volume instead of wmic logicaldisk:
wmicis deprecated since Windows 10 21H1 and produces\r-corrupted output.wmic logicaldiskshowsFileSystemas a text string that varies by locale on some configurations.Get-VolumereturnsFileSystemTypeas a typed enum value, includes health status, and provides accurate size calculations.
Method 2: Check a Specific Drive
When you need to verify a single drive's file system before performing an operation (like copying a large file), this method provides a targeted check with compatibility assessment.
@echo off
setlocal
set "Drive=%~1"
if "%Drive%"=="" (
echo Usage: %~nx0 ^<drive_letter^>
echo.
echo Examples:
echo %~nx0 C
echo %~nx0 E
echo %~nx0 F
endlocal
exit /b 1
)
:: Normalize - accept both "C" and "C:"
set "DriveLetter=%Drive:~0,1%"
:: Verify the drive exists
if not exist %DriveLetter%:\ (
echo [ERROR] Drive %DriveLetter%: does not exist or is not accessible. >&2
endlocal
exit /b 1
)
echo [INFO] File system details for %DriveLetter%:
echo.
powershell -NoProfile -Command ^
"$vol = Get-Volume -DriveLetter '%DriveLetter%' -ErrorAction SilentlyContinue;" ^
"if (-not $vol) { Write-Host 'Volume information not available.'; exit 1 };" ^
"Write-Host \" Drive: $('%DriveLetter%'):\";" ^
"Write-Host \" File System: $($vol.FileSystemType)\";" ^
"Write-Host \" Label: $(if ($vol.FileSystemLabel) { $vol.FileSystemLabel } else { '(none)' })\";" ^
"Write-Host \" Total Size: $([math]::Round($vol.Size / 1GB, 1)) GB\";" ^
"Write-Host \" Free Space: $([math]::Round($vol.SizeRemaining / 1GB, 1)) GB\";" ^
"Write-Host \" Health: $($vol.HealthStatus)\";" ^
"Write-Host '';" ^
"switch ([string]$vol.FileSystemType) {" ^
" 'NTFS' {" ^
" Write-Host ' Capabilities:';" ^
" Write-Host ' Max file size: 16 TB';" ^
" Write-Host ' Permissions: Full NTFS ACLs';" ^
" Write-Host ' Encryption: Supported (EFS, BitLocker)';" ^
" Write-Host ' Compression: Supported';" ^
" Write-Host ' Cross-platform: Windows only (read-only on macOS/Linux)'" ^
" }" ^
" 'FAT32' {" ^
" Write-Host ' Capabilities:';" ^
" Write-Host ' Max file size: 4 GB [!]' -ForegroundColor Yellow;" ^
" Write-Host ' Permissions: None';" ^
" Write-Host ' Encryption: Not supported';" ^
" Write-Host ' Cross-platform: Universal (Windows, macOS, Linux, cameras, TVs)'" ^
" }" ^
" 'exFAT' {" ^
" Write-Host ' Capabilities:';" ^
" Write-Host ' Max file size: Effectively unlimited';" ^
" Write-Host ' Permissions: None';" ^
" Write-Host ' Encryption: Not supported';" ^
" Write-Host ' Cross-platform: Windows, macOS, Linux (modern kernels)'" ^
" }" ^
" 'ReFS' {" ^
" Write-Host ' Capabilities:';" ^
" Write-Host ' Max file size: 35 PB';" ^
" Write-Host ' Permissions: Full ACLs';" ^
" Write-Host ' Resilience: Self-healing with integrity streams';" ^
" Write-Host ' Cross-platform: Windows Server only'" ^
" }" ^
" default {" ^
" Write-Host \" File system type '$($vol.FileSystemType)' - capabilities unknown.\"" ^
" }" ^
"}"
endlocal
exit /b 0
Sample output:
Drive: E:
File System: exFAT
Label: BACKUP_USB
Total Size: 119.2 GB
Free Space: 87.4 GB
Health: Healthy
Capabilities:
Max file size: Effectively unlimited
Permissions: None
Encryption: Not supported
Cross-platform: Windows, macOS, Linux (modern kernels)
Method 3: Pre-Copy File System Compatibility Check
Before copying a large file to a destination drive, this method checks whether the file system can handle the file size, preventing the frustrating "not enough space" error that FAT32 produces for files over 4 GB.
@echo off
setlocal
set "SourceFile=%~1"
set "DestDrive=%~2"
if "%DestDrive%"=="" (
echo Usage: %~nx0 ^<source_file^> ^<destination_drive_letter^>
echo.
echo Checks if the destination drive's file system can handle the file.
echo.
echo Example: %~nx0 "C:\Backups\database.bak" E
endlocal
exit /b 1
)
set "DestLetter=%DestDrive:~0,1%"
if not exist "%SourceFile%" (
echo [ERROR] Source file not found: %SourceFile% >&2
endlocal
exit /b 1
)
if not exist %DestLetter%:\ (
echo [ERROR] Destination drive %DestLetter%: not found. >&2
endlocal
exit /b 1
)
:: Get file size and destination info
for /f "tokens=1-4 delims=|" %%a in (
'powershell -NoProfile -Command ^
"$file = Get-Item -LiteralPath '%SourceFile%' -ErrorAction SilentlyContinue;" ^
"$vol = Get-Volume -DriveLetter '%DestLetter%' -ErrorAction SilentlyContinue;" ^
"if (-not $file -or -not $vol) { Write-Output 'ERROR|||'; exit 1 };" ^
"$fileMB = [math]::Round($file.Length / 1MB, 1);" ^
"$freeMB = [math]::Round($vol.SizeRemaining / 1MB, 1);" ^
"$fs = [string]$vol.FileSystemType;" ^
"Write-Output ($fileMB.ToString() + '|' + $freeMB.ToString() + '|' + $fs + '|' + $file.Length.ToString())"'
) do (
set "FileSizeMB=%%a"
set "FreeSpaceMB=%%b"
set "FileSystem=%%c"
set "FileSizeBytes=%%d"
)
if "%FileSizeMB%"=="ERROR" (
echo [ERROR] Could not read file or volume information. >&2
endlocal
exit /b 1
)
echo [INFO] File: %SourceFile% (%FileSizeMB% MB)
echo [INFO] Destination: %DestLetter%: (%FileSystem%, %FreeSpaceMB% MB free)
echo.
:: Check 1: Enough free space?
powershell -NoProfile -Command "if (%FileSizeMB% -gt %FreeSpaceMB%) { exit 1 } else { exit 0 }" >nul 2>&1
if errorlevel 1 (
echo [FAIL] Not enough free space on %DestLetter%: >&2
echo Need: %FileSizeMB% MB Available: %FreeSpaceMB% MB >&2
endlocal
exit /b 1
)
:: Check 2: FAT32 file size limit?
if /i "%FileSystem%"=="FAT32" (
rem FAT32 max file size is 4,294,967,295 bytes (4 GB - 1 byte)
powershell -NoProfile -Command "if (%FileSizeBytes% -ge 4294967296) { exit 1 } else { exit 0 }" >nul 2>&1
if errorlevel 1 (
echo [FAIL] File exceeds FAT32's 4 GB limit! >&2
echo File size: %FileSizeMB% MB >&2
echo FAT32 max: 4,096 MB (4 GB^) >&2
echo. >&2
echo Options: >&2
echo - Format the drive as exFAT: format %DestLetter%: /fs:exfat /q >&2
echo - Format the drive as NTFS: format %DestLetter%: /fs:ntfs /q >&2
echo - Split the file into smaller parts >&2
endlocal
exit /b 1
)
)
echo [PASS] File is compatible with %FileSystem% on %DestLetter%:
echo [PASS] Copy can proceed.
endlocal
exit /b 0
Why this check is valuable:
The FAT32 4 GB limit produces a misleading error message: "There is not enough space on the disk", even when the drive has 50 GB free. This causes users and scripts to waste time investigating free space when the actual problem is the file system limitation. The pre-copy check identifies the exact issue and suggests solutions.
Method 4: Fleet-Wide File System Audit
For auditing file system configurations across multiple machines, export the inventory to a shared CSV.
@echo off
setlocal
set "CSVFile=\\Server\Audit\filesystem_inventory.csv"
if not exist "%CSVFile%" (
echo "Timestamp","Computer","Drive","FileSystem","Label","TotalGB","FreeGB","Health" > "%CSVFile%" 2>nul
)
powershell -NoProfile -Command ^
"$ts = Get-Date -Format 'yyyy-MM-dd HH:mm:ss';" ^
"Get-Volume | Where-Object { $_.DriveLetter -and $_.FileSystemType } | ForEach-Object {" ^
" $totalGB = [math]::Round($_.Size / 1GB, 1);" ^
" $freeGB = [math]::Round($_.SizeRemaining / 1GB, 1);" ^
" $label = if ($_.FileSystemLabel) { $_.FileSystemLabel } else { 'none' };" ^
" Write-Output ('\"' + $ts + '\",\"' + $env:COMPUTERNAME + '\",\"' + $_.DriveLetter + ':\",\"' + $_.FileSystemType + '\",\"' + $label + '\",\"' + $totalGB + '\",\"' + $freeGB + '\",\"' + $_.HealthStatus + '\"')" ^
"}" >> "%CSVFile%" 2>nul
echo [OK] File system data exported for %COMPUTERNAME%.
endlocal
exit /b 0
What to look for in the fleet CSV:
- FAT32 on internal drives: Internal drives should use NTFS. FAT32 lacks permissions, journaling, and the 4 GB file limit causes failures.
- Unknown or blank file systems: Indicates RAW (unformatted) or corrupted volumes that need attention.
- Health ≠ Healthy: Warning or degraded health statuses require investigation.
- ReFS on workstations: ReFS is intended for Windows Server. Its presence on a workstation may indicate a misconfiguration.
How to Avoid Common Errors
Wrong Way: Assuming All USB Drives Are FAT32
Many modern USB drives ship pre-formatted as exFAT or NTFS. If your script assumes FAT32 and skips large file operations, it may unnecessarily fail on drives that can handle them.
Correct Way: Always check the file system before making compatibility decisions. Method 3 demonstrates this for pre-copy validation.
Wrong Way: Using wmic logicaldisk for File System Queries
:: DEPRECATED:wmic output contains \r characters
wmic logicaldisk get name, filesystem
wmic is deprecated and its output corruption can cause findstr and variable comparisons to fail.
Correct Way: Use Get-Volume in PowerShell, which returns typed values.
Problem: RAW (Unformatted) Volumes
A drive that appears in Disk Management but shows no file system is RAW, either newly created without formatting, or corrupted.
Solution: If the volume is new, format it:
format E: /fs:ntfs /q /v:DataDrive
If the volume previously contained data and became RAW, attempt repair with chkdsk E: /f before formatting (which destroys all data).
Problem: fsutil Requires Admin for Some Queries
While fsutil fsinfo volumeinfo works for basic information, some fsutil queries require elevation.
Solution: Use Get-Volume (Method 1), which works without elevation for read-only queries.
Best Practices and Rules
1. Use NTFS for All Internal Drives
NTFS provides file permissions (ACLs), journaling (crash protection), encryption (EFS), compression, and large file support. There is no reason to use FAT32 or exFAT on internal Windows drives.
2. Use exFAT for Cross-Platform External Media
If a USB drive or SD card needs to work on both Windows and macOS with files larger than 4 GB, exFAT is the correct choice. It is supported natively on Windows, macOS, and modern Linux kernels.
3. Check Before Copying Large Files
Before copying files over 4 GB to removable media, verify the destination file system. Method 3 provides an automated pre-copy check that catches the FAT32 limitation before the copy fails.
4. Include File System in Storage Audits
When auditing disk space, include the file system type. A drive's capabilities depend on its file system, knowing the space without knowing the file system is incomplete information.
5. Monitor Volume Health
Get-Volume includes a HealthStatus property. Volumes with Warning or Degraded status may be developing hardware issues. Include health in regular audits (Method 4).
Conclusions
Identifying the file system type of your drives is a fundamental prerequisite for any storage management task. By using Get-Volume for comprehensive inventories, providing capability summaries for each file system type, and performing pre-copy compatibility checks, you prevent the silent failures and misleading errors that occur when scripts encounter file system limitations unexpectedly. This awareness is essential for anyone managing diverse storage devices across a Windows environment.