Count lines of code per file type
Symptoms
You have source code in a folder and want to count the total number of lines per file type.
Cause
n/a
Resolution
This script starts in a root folder and recurses. If there is a .gitIgnore file it will ignore files and paths specified within there. Results are saved to a CSV file.
Define the folder to explore
$folderPath = "C:\PathToProject" $outputFilePath = "$folderPath\results-summary.csv" $gitIgnorePath = "$folderPath.gitignore"
Function to get the patterns from the .gitignore file
function Get-GitIgnorePatterns { param ( [string]$gitIgnorePath )
if (Test-Path $gitIgnorePath) {
Get-Content $gitIgnorePath | Where-Object {
$_ -and -not $_.StartsWith('#') -and -not $_.Trim().StartsWith('!')
}
} else {
return @() # Return empty if no .gitignore found
}
}
Function to check if a path matches any pattern in the .gitignore
function Is-IgnoredPath { param ( [string]$path, [array]$patterns )
foreach ($pattern in $patterns) {
# Convert gitignore patterns to match file/directory paths in a flexible way
$regexPattern = [regex]::Escape($folderPath + "\" + $pattern).Replace("\\*", ".*").Replace("\\?", ".")
if ($path -like $regexPattern) {
return $true
}
}
return $false
}
Get all patterns from .gitignore
$gitIgnorePatterns = Get-GitIgnorePatterns -gitIgnorePath $gitIgnorePath
Initialize a hashtable to store file extensions, file counts, and line counts
$fileStats = @{}
Get all files from the folder and subfolders
Get-ChildItem -Path $folderPath -Recurse -File | ForEach-Object { $file = $_ $filePath = $file.FullName
# Skip files and folders that match the .gitignore patterns
if (Is-IgnoredPath -path $filePath -patterns $gitIgnorePatterns) {
return
}
$extension = $file.Extension.ToLower()
# Initialize the extension in the hashtable if it doesn't exist
if (-not $fileStats.ContainsKey($extension)) {
$fileStats[$extension] = @{
FileCount = 0
LineCount = 0
}
}
# Increment the file count
$fileStats[$extension].FileCount++
# Get the number of lines in the file and add to the line count
$lineCount = (Get-Content $file.FullName | Measure-Object -Line).Lines
$fileStats[$extension].LineCount += $lineCount
}
Prepare the output data as a list of custom objects
$outputData = foreach ($extension in $fileStats.Keys) { $fileInfo = $fileStats[$extension] [PSCustomObject]@{ Extension = $extension FileCount = $fileInfo.FileCount LineCount = $fileInfo.LineCount } }
Export the data to a CSV file
$outputData | Export-Csv -Path $outputFilePath -NoTypeInformation
Inform the user
Write-Host "Results exported to $outputFilePath"