Count lines of code per file type

Created by Jeremy Burgess, Modified on Tue, 24 Sep at 2:42 PM by Jeremy Burgess

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"

Was this article helpful?

That’s Great!

Thank you for your feedback

Sorry! We couldn't be helpful

Thank you for your feedback

Let us know how can we improve this article!

Select at least one of the reasons
CAPTCHA verification is required.

Feedback sent

We appreciate your effort and will try to fix the article