Last active
October 8, 2019 12:03
-
-
Save pldmgg/d1657845463554451bc914c8d0420d5d to your computer and use it in GitHub Desktop.
New-SymFS.ps1
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
| $StartTime = Get-Date | |
| # Setup initial parameters | |
| try { | |
| $UserDirName = $(Get-Item $HOME).Name | |
| $GoogleDrivePath = "$HOME\Google Drive" | |
| $GDUserPath = "$GoogleDrivePath\$UserDirName" | |
| $LogFileName = "NewSymFS_Log_" + $(Get-Date -Format MMddyy_hhmmss) + '.log' | |
| $LogFileDir = "E:\" | |
| $LogFilePath = $LogFileDir + $LogFileName | |
| $FileAgeInMonths = 12 | |
| $FileAgeInDays = $FileAgeInMonths*30.5 | |
| $FileTimeSpan = New-Timespan -Days $FileAgeInDays | |
| $HomeDirFoldersToExclude = @( | |
| "Google Drive" | |
| #"AppData" | |
| ) | |
| $HomeDirItems = Get-ChildItem -Path $HOME -Directory -Force | Where-Object {$HomeDirFoldersToExclude -notcontains $_.Name} | |
| } | |
| catch { | |
| Write-Error $_ | |
| if ($LogFileName) { | |
| $_ >> "$HOME\$LogFileName" | |
| } | |
| $global:FunctionResult = "1" | |
| return | |
| } | |
| # Make sure the $LogFileDir exists | |
| try { | |
| if (!$(Test-Path $LogFileDir)) { | |
| $null = New-Item -ItemType Directory -Path $LogFileDir -Force -ErrorAction Stop | |
| } | |
| } | |
| catch { | |
| Write-Error $_ | |
| $_ >> "$HOME\$LogFileName" | |
| $global:FunctionResult = "1" | |
| return | |
| } | |
| # Make sure we're running PowerShell 7 | |
| if ($PSVersionTable.PSVersion.Major -lt 7) { | |
| $ErrMsg = "This script must be run using PowerShell Core version 7 or greater! Halting!" | |
| Write-Error $ErrMsg | |
| $ErrMsg >> $LogFilePath | |
| $global:FunctionResult = 1 | |
| return | |
| } | |
| # Make sure $HOME\Google Drive exists | |
| if (!$(Test-Path $GoogleDrivePath)) { | |
| $ErrMsg = "The path $GoogleDrivePath was not found! Halting!" | |
| Write-Error $ErrMsg | |
| $ErrMsg >> $LogFilePath | |
| $global:FunctionResult = "1" | |
| return | |
| } | |
| # Make sure $GDUserPath exists | |
| if (!$(Test-Path $GDUserPath)) { | |
| try { | |
| $null = New-Item -ItemType Directory -Path $GDUserPath -ErrorAction Stop | |
| if (!$(Test-Path $GDUserPath)) { | |
| throw "The path $GDUserPath still wasn't created eventhough New-Item didn't throw an error!" | |
| } | |
| } | |
| catch { | |
| Write-Error $_ | |
| $_ >> $LogFilePath | |
| $global:FunctionResult = "1" | |
| return | |
| } | |
| } | |
| # First, get all directories recursively under $HOME and recreate them (for real) under $GDUserPath so that | |
| # they actually appear in Google Drive | |
| $(Get-Date).ToString() >> $LogFilePath | |
| "`n##### CREATING DIRECTORIES #####`n" >> $LogFilePath | |
| foreach ($HDI in $HomeDirItems) { | |
| try { | |
| $ParentNewPath = $HDI.FullName -replace [regex]::Escape($HOME),$GDUserPath | |
| if (!$(Test-Path $ParentNewPath)) { | |
| $null = New-Item -ItemType Directory -Path $ParentNewPath -ErrorAction Stop | |
| } | |
| Get-ChildItem -Recurse -Path $HDI.FullName -Directory -Force -ErrorAction SilentlyContinue | foreach { | |
| $NewPath = $_.FullName -replace [regex]::Escape($HOME),$GDUserPath | |
| if (!$(Test-Path $NewPath)) { | |
| $null = New-Item -ItemType Directory -Path $NewPath -ErrorAction Stop | |
| } | |
| } | |
| } | |
| catch { | |
| $_ >> $LogFilePath | |
| } | |
| } | |
| # Next, iterate over all files under $HOME. | |
| # If the file is too old, create a symlink under the Google Drive folder so that Google Backup and Sync does NOT actually sync it to Google Drive | |
| # If the file is recent enough, move it to the Google Drive folder and create a hard link from where it was to where it is now (under Google Drive folder) | |
| # Creating a hard link should prevent any problems with programs not expecting a symlink and also not take up any additional space on the HDD | |
| $(Get-Date).ToString() >> $LogFilePath | |
| "`n##### CREATING SYMLINKS AND HARDLINKS #####`n" >> $LogFilePath | |
| foreach ($HDI in $HomeDirItems) { | |
| Get-ChildItem -Recurse -Path $HDI.FullName -File -Force -ErrorAction SilentlyContinue | foreach { | |
| $NewPath = $_.FullName -replace [regex]::Escape($HOME),$GDUserPath | |
| $TestPathCheck = Test-Path $NewPath | |
| try { | |
| if ($_.LastWriteTime -le $(Get-Date).Subtract($FileTimeSpan)) { | |
| # Then the file is too old and should NOT be synced to Google Drive | |
| # If the path doesn't exist, or if it is does exist but is *not* a symlink, create a symlink | |
| if (!$TestPathCheck) { | |
| #Write-Host "$($_.FullName) is too old!" | |
| #Write-Host "LastWriteTime is $($_.LastWriteTime)" | |
| $null = New-Item -ItemType SymbolicLink -Path $NewPath -Target $_.FullName -ErrorAction Stop | |
| } | |
| elseif ($TestPathCheck) { | |
| if ($(Get-Item $NewPath -ErrorAction SilentlyContinue).LinkType -ne 'SymbolicLink') { | |
| $null = Remove-Item $NewPath -Force -ErrorAction SilentlyContinue | |
| $null = New-Item -ItemType SymbolicLink -Path $NewPath -Target $_.FullName -ErrorAction Stop | |
| } | |
| } | |
| } | |
| else { | |
| # The file is recent enough that it SHOULD be synced to Google Drive | |
| # If the path doesn't exist, or if it is does exist but is *not* a hardlink, create a symlink | |
| if (!$TestPathCheck) { | |
| #Write-Host "$($_.FullName) is recent enough!" | |
| #Write-Host "LastWriteTime is $($_.LastWriteTime)" | |
| #$null = Move-Item -Path $_.FullName -Destination $NewPath | |
| #$null = Invoke-Expression "cmd /c mklink /h `"$NewPath`" `"$($_.FullName)`"" -ErrorAction SilentlyContinue >> $LogFilePath | |
| $null = New-Item -ItemType HardLink -Path $NewPath -Target $_.FullName -ErrorAction Stop | |
| } | |
| elseif ($TestPathCheck) { | |
| if ($(Get-Item $NewPath -ErrorAction SilentlyContinue).LinkType -ne 'HardLink') { | |
| $null = Remove-Item $NewPath -Force -ErrorAction SilentlyContinue | |
| $null = New-Item -ItemType HardLink -Path $NewPath -Target $_.FullName -ErrorAction Stop | |
| } | |
| } | |
| } | |
| } | |
| catch { | |
| $_ >> $LogFilePath | |
| } | |
| } | |
| } | |
| $EndTime = Get-Date | |
| "`n##### TOTAL RUNTIME #####`n" >> $LogFilePath | |
| $TotalTime = $EndTime - $StartTime | |
| $TotalTime >> $LogFilePath |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment