Search code examples
powershelltreeviewstdout

Printing tree of windows directory where the script located and exclude some folders based on .gitignore file


I have this powershell script that fully generated by ChatGPT because I know nothing about powershell. Instead, I prefer Bash.

show-tree.ps1

# Get the base path of the script
$scriptPath = Split-Path -Parent $MyInvocation.MyCommand.Path
$basePath = (Get-Item $scriptPath).FullName

# Define the path to the .gitignore file
$gitIgnorePath = Join-Path $basePath ".gitignore"

# Check if the PSTree module is installed
if (-not (Get-Module -ListAvailable -Name PSTree)) {
  # Install the PSTree module if it's not installed
  Install-Module -Name PSTree -Scope CurrentUser -Force -AllowClobber
}

# Check if the .gitignore file exists
if (Test-Path $gitIgnorePath -PathType Leaf) {
  # Read the patterns from the .gitignore file and split into an array
  $excludePatterns = Get-Content $gitIgnorePath -ErrorAction SilentlyContinue | ForEach-Object { "$basePath\$_" }

  # Import the PSTree module
  Import-Module PSTree
  
  $tmpStdout = "tmp.txt"

  # Use the base path and exclude patterns in the Get-PSTree command
  Get-PSTree -Exclude $excludePatterns | Out-File $tmpStdout

  # Read the contents of the file
  $lines = Get-Content -Path $tmpStdout
  # Define the number of lines to skip from the beginning and end
  $headLength = 6   # Number of lines to skip from the beginning
  $tailLength = 2   # Number of lines to keep at the end
  # Filter the lines based on the specified criteria
  $lines[$headLength..($lines.Count - $tailLength - 1)] | Out-File $tmpStdout

  # Read the content of the input file
  $content = Get-Content $tmpStdout
  # Process each line, cutting the first 23 characters
  $content | ForEach-Object { $_.Substring(23) } | Out-File $tmpStdout
  Get-Content $tmpStdout
  Remove-Item $tmpStdout

}
else {
  Write-Host "No .gitignore file found."

  # Import the PSTree module without exclusion
  Import-Module PSTree
  Get-PSTree
}

It works fine. It returns

cf-ztna-app
├── .gitignore
├── README.md
├── requirements.txt
├── show-tree.ps1
├── start-server.cmd
├── tmp.txt
└── src
    ├── main.py
    └── __init__.py

Here is my .gitignore:

.venv
.env

But as you see, I have in eficient code that using temporary file to store output. I'm using Out-File $tmpStdout.

Why I'm doing this? Because I simply want take the tree output, not any overhead or unnecesary info from PSTree command external module (not built-int). The built-in tree command from windows didn't provide exclude flag.

Here is original output that I don't want to expect:



   Source: C:\Users\User\Documents\KULIAH\LAB_SOFTWARE\python_proj\cf-ztna-app

Mode            Length Hierarchy                                                               
----            ------ ---------                                                               
d-----         2.84 KB cf-ztna-app                                                             
-a----        10.00  B ├── .gitignore                                                          
-a----         1.11 KB ├── README.md                                                           
-a----        14.00  B ├── requirements.txt                                                    
-a----         1.70 KB ├── show-tree.ps1                                                       
-a----         0.00  B ├── start-server.cmd                                                    
-a----         0.00  B ├── tmp.txt                                                             
d-----       126.00  B └── src                                                                 
-a----       105.00  B     ├── main.py                                                         
-a----        21.00  B     └── __init__.py                                                     



Many empty lines and unnecessary info Source.

Reply for @SantiagoSquarzon , it didn't exclude content of .gitignore:

(.venv) PS C:\Users\User\Documents\KULIAH\LAB_SOFTWARE\python_proj\cf-ztna-app> (Get-PSTree -Exclude *.gitignore*).Hierarchy
cf-ztna-app
├── .env
├── README.md
├── requirements.txt
├── show-tree.ps1
├── start-server.cmd
├── tmp.txt
├── src
│   ├── main.py
│   └── __init__.py
└── .venv
    ├── pyvenv.cfg
    ├── Scripts
    │   ├── activate
    │   ├── activate.bat
    │   ├── Activate.ps1
    │   ├── deactivate.bat
    │   ├── httpx.exe
    │   ├── pip.exe
    │   ├── pip3.11.exe
    │   ├── pip3.9.exe
    │   ├── pip3.exe
    │   ├── python.exe
    │   └── pythonw.exe
    ├── Lib
    │   └── site-packages
    └── Include

Solution

  • Basically you're looking to expand the .Hierarchy property from the Get-PSTree output, you can simplify your code with this:

    # Define the path to the .gitignore file
    $gitIgnorePath = Join-Path $PSScriptRoot '.gitignore'
    
    # Check if the PSTree module is installed
    if (-not (Get-Module -ListAvailable -Name PSTree)) {
        # Install the PSTree module if it's not installed
        Install-Module -Name PSTree -Scope CurrentUser -Force -AllowClobber
    }
    
    # Check if the .gitignore file exists
    if (Test-Path $gitIgnorePath -PathType Leaf) {
        # Read the patterns from the .gitignore file and split into an array
        $excludePatterns = Get-Content $gitIgnorePath -ErrorAction SilentlyContinue |
            ForEach-Object { Join-Path $PSScriptRoot $_ }
    
        # Use the base path and exclude patterns in the Get-PSTree command
        (Get-PSTree -Exclude $excludePatterns).Hierarchy
    }
    else {
        Write-Host 'No .gitignore file found.'
        Get-PSTree
    }
    

    Note that $PSScriptRoot already contains the root script path. Also remember that the cmdlet will use -Depth 3 by default, if you want to display the complete hierarchy you should use -Recurse.