Created
June 6, 2022 11:57
-
-
Save DrBob5188/36d587b5c2f6e6238bc948af241bed0f to your computer and use it in GitHub Desktop.
Answer to reddit question https://www.reddit.com/r/PowerShell/comments/v5ey6d/powershell_command_to_move_files_to_fodlers_with/?utm_source=share&utm_medium=web2x&context=3
This file contains 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
function Get-StringLCP | |
{ | |
<# | |
.SYNOPSIS | |
Get the longest common string prefix from an array of strings. | |
.DESCRIPTION | |
Get the longest common string prefix from an array of strings. | |
Note that empty strings and null values are allowed in the array. | |
Nulls will be automatically type cast by PowerShell as an empty string. | |
Use the IgnoreEmptyStrings switch to stop processing empty strings. | |
.PARAMETER InputStrings | |
The array of strings from which the longest common prefix is sought. | |
.PARAMETER IgnoreEmptyStrings | |
Excludes empty strings from the processing. Use this option when the input | |
data may have nulls or empty strings. If a null or empty string is present | |
the return value will always be [string]::Empty | |
.PARAMETER IgnoreCase | |
Performs case insensitive comparisons on the strings | |
.INPUTS | |
<None> | |
.OUTPUTS | |
[string] | |
.NOTES | |
Version: 1.0 | |
Author: Robert Thomson | |
Creation Date: 2022-03-19 | |
Purpose/Change: Initial rewrite of code at rosettacode.org, as an advanced | |
function with options for case insensitive comparison and empty string | |
filtering. | |
References: | |
1) Longest common prefix - Rosetta Code. Rosettacode.org. (2022). | |
Retrieved 19 March 2022, from | |
https://rosettacode.org/wiki/Longest_common_prefix#PowerShell. | |
.EXAMPLE | |
Get-StringLCP -InputStrings @('foo', 'foobar') | |
This example performs a case-sensitive comparison to return 'foo'. | |
.EXAMPLE | |
Get-StringLCP -InputStrings @('foo', 'FOOBAR') -IgnoreCase | |
This example performs a case-insensitive comparison to return 'foo'. | |
.EXAMPLE | |
Get-StringLCP -InputStrings @('foo', $null, 'foobar') | |
Get-StringLCP -InputStrings @('foo', '', 'foobar') | |
These examples are equivalent and perform a case-sensitive comparison to return ''. | |
.EXAMPLE | |
Get-StringLCP -InputStrings @('foo', $null, 'foobar') -IgnoreEmptyStrings | |
Get-StringLCP -InputStrings @('foo', '', 'foobar') -IgnoreEmptyStrings | |
These examples are equivalent and perform a case-sensitive comparison to return 'foo'. | |
#> | |
[CmdletBinding()] | |
param( | |
[parameter(Mandatory)] | |
[AllowEmptyCollection()] | |
[AllowEmptyString()] | |
[string[]]$InputStrings, | |
[parameter()] | |
[Switch]$IgnoreEmptyStrings, | |
[parameter()] | |
[Switch]$IgnoreCase | |
) | |
if ($IgnoreEmptyStrings.IsPresent) { | |
$arr = ($InputStrings | Where-Object { | |
![String]::IsNullOrEmpty($_) | |
} | Sort-Object -Property {$_.length} | Select-Object -unique) -as [String[]] | |
} | |
else { | |
$arr = ($InputStrings | Sort-Object -Property {$_.length} | Select-Object -unique) -as [String[]] | |
} | |
switch ($arr.count) { | |
# Array is null or empty | |
0 {[string]::Empty} | |
# Longest common prefix of a single string is the string | |
1 {$arr[0]} | |
# Process 2 or more strings. | |
default { | |
$Limit = $arr[0].length | |
$i = 0 | |
$test = $true | |
# Configure the grouping property scriptblock for case insensitive if required | |
if ($IgnoreCase.IsPresent) { | |
$sb = {[char]::ToUpper($_[$i])} | |
} | |
else { | |
$sb = {$_[$i]} | |
} | |
while (($i -lt $Limit) -and $test) { | |
# Group by letter. If the letters are the same for all the strings there will be only one group | |
$test = ($arr | Group-Object -Property $sb ).Name.Count -eq 1 | |
if ($test) { | |
$i++ | |
} | |
} | |
$arr[0].substring(0,$i) | |
} | |
} | |
} | |
# Main script part (untested) | |
$files = Get-ChildItem -Path .\ -File | |
$filenames = $files.Name | |
$Start = $End = 0 | |
while ($start -lt $filenames.count -and $end -lt $filenames.count) { | |
do { | |
$lcp = Get-StringLCP -IgnoreCase -InputStrings $filenames[$start..$end++] | |
} while (-not [string]::IsNullOrEmpty($lcp)) | |
if (($end - $start) -gt 1) { | |
$lcp = Get-StringLCP -IgnoreCase -InputStrings $filenames[$start..($end - 1)] | |
New-Item -Path ".\$lcp" -ItemType Directory | |
Move-Item -path $filenames[$start..($end - 1)] -Destination ".\$lcp" | |
} | |
$start = $End | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment