PS: Custom File-Structures for Projects
Often, when working with projects, you’ll need to generate a file-structure. Why not automate this using PowerShell?
The standard way to create new files/directories in PowerShell is through the New-Item (ni)
cmdlet. Why not customize it to create the whole file-structure for your project?
This example creates file-structure with blank files for a web project & opens them in your favourite editor:
<#
.SYNOPSIS
Creates custom project file-structure.
.EXAMPLE
New-ItemX -Web
nix -Web
#>
function New-ItemX{
[cmdletBinding()]
[Alias('nix')]
param(
[switch]$Web,
[switch]$Notes,
[switch]$Python,
[switch]$PowerShell
)
$State = ""
switch ($PSBoundParameters.keys){
'Web' {
$State = "vim -p index.html js/main.js css/style.css"
New-Item -ItemType 'directory' -Path js,css,media,fonts,common
New-Item -ItemType 'file' -Path index.html,js/main.js,css/style.css
$State
}
}
}
13-02-2021 (07:12 PM)
The next question is - What if you accidentally closed all your files? How would you open them all at once?
One way is to save the open-files command in a global variable ($State
). However, this is lost upon closing the current session window.
We can export this variable into a XML file to solve this, and include an import statement in your user $PROFILE
to ensure that it is available across all sessions.
Also, we can conditionally import this variable - ie, only if it exists.
We can even encrypt/decrypt storage of this variable, but this would be an overkill.
function New-ItemX{
[cmdletBinding()]
[Alias('nix')]
param(
[switch]$Web,
[switch]$Notes,
[switch]$Python,
[switch]$PowerShell
)
$global:State = ""
switch ($PSBoundParameters.keys){
'Web' {
$global:State = "vim -p index.html js/main.js css/style.css"
New-Item -ItemType 'directory' -Path js,css,media,fonts,common
New-Item -ItemType 'file' -Path index.html,js/main.js,css/style.css
$State | Export-CliXML ~\states.ps1xml
Invoke-Expression $State
}
}
}
if ([System.IO.File]::Exists("$HOME\states.ps1xml")){
$State = Import-CliXML "$HOME\states.ps1xml"
}
Now, opening your last project is easy - just use iex $State
.
13-02-2021 (08:04 PM)
Did you try it out?
We accidentally left out a serious flaw with the code - we didn’t take into account that we’re using relative paths for opening up files. Hence, each iex $State
call just creates new files.
Oh, the joys of software!
Thankfully, we can resolve this by listing & using the absolute paths of each file (using Get-ChildItem
).
To ensure spaces in filepaths don’t become an issue (eg. C:\Users\Chaitanya Tejaswi\...
), we’ll wrap them in ""
.
function New-ItemX{
[cmdletBinding()]
[Alias('nix')]
param(
[switch]$Web,
[switch]$Notes,
[switch]$Python,
[switch]$PowerShell
)
$global:State = ""
$Files = ""
switch ($PSBoundParameters.keys){
'Web' {
New-Item -ItemType 'directory' -Path js,css,media,fonts,common
New-Item -ItemType 'file' -Path index.html,js/main.js,css/style.css
(Get-ChildItem index.html,js/main.js,css/style.css).FullName | forEach {$Files += '"'+$_+'" '}
$global:State = "vim -p $Files"
$State | Export-CliXML ~\states.ps1xml
Invoke-Expression $State
}
}
}
This does it for now. Phew!