Created
July 22, 2012 19:23
-
-
Save chklauser/3160775 to your computer and use it in GitHub Desktop.
PowerShell script to make ~\Documents more usable, hides directories and makes them accessible via a symlink in a different location.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
param( | |
[Parameter(Position=0)] | |
$Item, | |
[Switch] $WhatIf, | |
[String] $AppConfig = "$env:HOMEDRIVE$env:HOMEPATH\AppConfig", | |
[String] $BaseDir = ".", | |
[Parameter(ParameterSetName="register")] | |
[Switch] | |
$Register, | |
[Parameter(ParameterSetName="unregister")] | |
[Switch] | |
$Unregister); | |
# Clean up your ~, and ~\Documents directories on Windows while not breaking any of the applications that use it | |
# Usage: .\Manage-AppConfig.ps1 -Register Documents\SomeStupidApp | |
# Will | |
# - create a symlink to Documents\SomeStupidApp in ~\AppConfig\Documents\SomeStupidApp | |
# - hide Documents\SomeStupidApp | |
# | |
# You can configure ~\AppConfig to be something different, I wouldn't necessarily use ~\AppData, though because I have seen programs that use BOTH locations :-( | |
# By default the path under ~\AppConfig is the same as the path you specified (MUST be relative), but you can also explicitly specify the BasePath. | |
# | |
# Provided AS IS. It might not work. It might break something and destroy 5 years of your hard work in 5 seconds, or less. | |
$ErrorActionPreference = "stop"; | |
Write-Debug "Item: $Item"; | |
Write-Debug "BaseDir: $BaseDir"; | |
Write-Debug "AppConfig: $AppConfig"; | |
$WhatIfPreference = $WhatIf; | |
function Get-Attributes($Path){ | |
(Get-Item -Path $Path).Attributes | |
} | |
function Hide-File($Path){ | |
$i = Get-Item $Path -Force; | |
if(-not ($i.Attributes -match "Hidden")){ | |
$i.Attributes = @("Hidden") + $i.Attributes; | |
} | |
} | |
function Unhide-File($Path){ | |
$i = Get-Item $Path -Force; | |
Write-Debug "unhiding: $($i.Attributes)"; | |
if($i.Attributes -match "Hidden"){ | |
$n = [IO.FileAttributes]($i.Attributes -bxor [IO.FileAttributes]::Hidden) | |
Write-Debug "newattributes: $n" | |
$i.Attributes = $n; | |
} | |
} | |
if(-not (Test-Path $AppConfig)){ | |
Write-Debug "AppConfig at $AppConfig does not exist. Creating it now." | |
New-Item $AppConfig -ItemType "directory"; | |
} | |
function Check-Status($Path){ | |
$AbsolutePath = [System.IO.Path]::GetFullPath((Join-Path $BaseDir $Path)); | |
if(-not (Test-Path $AbsolutePath)){ | |
Write-Debug "Cannot find item to manage: $AbsolutePath" | |
throw "Cannot find item to manage: $AbsolutePath"; | |
} | |
$Item = Get-Item $Path -Force; # -Force because hidden items will not be found otherwise | |
$MirrorPath = [System.IO.Path]::GetFullPath((Join-Path $AppConfig $Path)); | |
if(Test-Path $MirrorPath){ | |
Write-Debug "Mirror $MirrorPath exists"; | |
$mirror = Get-Item $MirrorPath; | |
if([bool]((Get-Attributes $MirrorPath) -band [System.IO.FileAttributes]::ReparsePoint)){ | |
Write-Debug "Mirror $MirrorPath is a reparse point"; | |
if($mirror.ReparsePoint.Target -eq $Item.FullName){ | |
Write-Debug "Mirror $MirrorPath already points to $Item."; | |
$status = "exists"; | |
} else { | |
Write-Debug "Mirror $MirrorPath points to different item $($mirror.ReparsePoint.Target)"; | |
$status = "conflicting"; | |
} | |
} else { | |
Write-Debug "Found ordinary file/directory in mirror at $mirror."; | |
$status = "invalid"; | |
} | |
} else { | |
Write-Debug "Mirror $MirrorPath does not exist (yet)." | |
$status = "none"; | |
} | |
} | |
$visibilityAction = "none"; | |
switch($PsCmdlet.ParameterSetName){ | |
"register" { | |
Write-Debug "Register $Item into AppConfig at $AppConfig."; | |
. Check-Status $Item | |
switch ($status){ | |
"exists" { | |
Write-Verbose "Correct mirror already exists at $MirrorPath."; | |
$visibilityAction = "hide"; | |
break; | |
} | |
"invalid" { | |
Write-Error "Ther mirror's location is occupied by a different item: $mirror (not a reparse-point)"; | |
break; | |
} | |
"conflicting" { | |
Write-Error "There is already a mirror in place pointing at a different location: $($mirror.ReparsePoint.Target)"; | |
break; | |
} | |
"none" { | |
Write-Verbose "Installing mirror from $MirrorPath to $Item."; | |
$fp = [System.IO.Path]::GetFullPath($MirrorPath); | |
if($WhatIf){ | |
Write-Host "Creating symlink from $fp to $Item."; | |
} else { | |
Write-Debug "fp=$fp"; | |
New-Item -ItemType "directory" -Force ([IO.Path]::GetDirectoryName($fp)) | |
New-Symlink "$fp" -TargetPath "$Item"; | |
} | |
$visibilityAction = "hide"; | |
break; | |
} | |
default { | |
Write-Error "Unknown state."; | |
break; | |
} | |
} | |
break; | |
} | |
"unregister" { | |
Write-Debug "Unregister $Item from AppConfig at $AppConfig."; | |
. Check-Status $Item | |
switch ($status){ | |
"exists" { | |
Write-Verbose "Expected mirror found at at $MirrorPath. Removing it."; | |
if($Whatif){ | |
Write-Host "Removing reparse point at $MirrorPath."; | |
} else { | |
Remove-ReparsePoint "$MirrorPath"; | |
} | |
$visibilityAction = "show"; | |
break; | |
} | |
"invalid" { | |
Write-Error "Ther mirror's location is occupied by a different item: $mirror"; | |
break; | |
} | |
"conflicting" { | |
Write-Error "The mirror points at a different location than expected: $($mirror.ReparsePoint.Target)"; | |
break; | |
} | |
"none" { | |
Write-Verbose "No mirror found at $MirrorPath."; | |
$visibilityAction = "show"; | |
break; | |
} | |
default { | |
Write-Error "Unknown state."; | |
break; | |
} | |
} | |
break; | |
} | |
} | |
switch($visibilityAction){ | |
"show" { | |
Write-Verbose "Un-hiding $Item"; | |
Unhide-File $Item; | |
break; | |
} | |
"hide" { | |
Write-Verbose "Hiding $Item"; | |
Hide-File $Item; | |
break; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment