Skip to content

Instantly share code, notes, and snippets.

@changbowen
Last active April 28, 2020 18:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save changbowen/fec95ece2060d2c5b8e8ca40a1acccac to your computer and use it in GitHub Desktop.
Save changbowen/fec95ece2060d2c5b8e8ca40a1acccac to your computer and use it in GitHub Desktop.
function natualSort {
PARAM(
[System.Collections.ArrayList]$Array,
[switch]$Descending
)
Add-Type -TypeDefinition @'
using System;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.InteropServices;
namespace NaturalSort {
public static class NaturalSort
{
[DllImport("shlwapi.dll", CharSet = CharSet.Unicode)]
public static extern int StrCmpLogicalW(string psz1, string psz2);
public static System.Collections.ArrayList Sort(System.Collections.ArrayList foo)
{
foo.Sort(new NaturalStringComparer());
return foo;
}
}
public class NaturalStringComparer : IComparer
{
public int Compare(object x, object y)
{
return NaturalSort.StrCmpLogicalW(x.ToString(), y.ToString());
}
}
}
'@
$Array.Sort((New-Object NaturalSort.NaturalStringComparer))
if ($Descending) {
$Array.Reverse()
}
return $Array
}
Write-Output "`n-----------------------`n Referenced Renaming`n-----------------------"
while ($true) {
$refDir = Read-Host -Prompt "`nReference folder"
if (![System.IO.Directory]::Exists($refDir)) {
Write-Error "Directory is invalid.";
continue;
}
$refReg = Read-Host -Prompt "`nFile name regex [default: .*]"
if ([string]::IsNullOrWhiteSpace($refReg)) {
$refReg = ".*";
}
$refList = @(natualSort $(Get-ChildItem -LiteralPath $refDir)) -match $refReg;
if ($refList.Count -eq 0) {
Write-Error "Reference file list is empty.";
continue;
}
break;
}
while ($true) {
$tgtDir = Read-Host -Prompt "`nTarget folder containing files to rename (leave empty to use same value as the reference)"
if ([string]::IsNullOrWhiteSpace($tgtDir)) {
$tgtDir = $refDir;
}
elseif (![System.IO.Directory]::Exists($tgtDir)) {
Write-Error "Directory is invalid.";
continue;
}
$tgtReg = Read-Host -Prompt "`nFile name regex (leave empty to use same value as the reference)"
if ([string]::IsNullOrWhiteSpace($tgtReg)) {
$tgtReg = $refReg;
}
$tgtList = @(natualSort $(Get-ChildItem -LiteralPath $tgtDir)) -match $tgtReg;
if ($tgtList.Count -eq 0) {
Write-Error "Target file list is empty.";
continue;
}
break;
}
while ($true) {
Write-Host "`nNew Name Template"
Write-Host "Use <ref_name> to indicate referenced name without extension and <ref_ext> to indicate its extension with preceding dot."
Write-Host "Use <tgt_name> to indicate target name without extension and <tgt_ext> to indicate its extension with preceding dot."
Write-Host "Default template is <ref_name><tgt_ext>"
$template = Read-Host -Prompt "Template";
if ([string]::IsNullOrWhiteSpace($template)) {
$template = "{0}{3}";
}
else {
$template = $template.Replace('<ref_name>', '{0}').Replace('<ref_ext>', '{1}').Replace('<tgt_name>', '{2}').Replace('<tgt_ext>', '{3}');
}
$postReg = Read-Host -Prompt "Post replace with Regex (leave empty to skip)"
if (![string]::IsNullOrWhiteSpace($postReg)) {
$postRegRep = Read-Host -Prompt "Replace string";
}
# preview list
for ($i = 0; $i -lt ($refList.Count, $tgtList.Count | Measure-Object -Minimum).Minimum; $i++) {
$newName = $template -f $refList[$i].BaseName, $refList[$i].Extension, $tgtList[$i].BaseName, $tgtList[$i].Extension;
if (![string]::IsNullOrWhiteSpace($postRegRep)) {
$newName = $newName -replace $postReg, $postRegRep;
}
Write-Output ($tgtList[$i].Name + ' --> ' + $newName);
}
# rename
if ((Read-Host -Prompt "Is this OK? (Y/N)").IndexOf('y', [System.StringComparison]::OrdinalIgnoreCase) -eq 0) {
for ($i = 0; $i -lt ($refList.Count, $tgtList.Count | Measure-Object -Minimum).Minimum; $i++) {
$newName = $template -f $refList[$i].BaseName, $refList[$i].Extension, $tgtList[$i].BaseName, $tgtList[$i].Extension;
if (![string]::IsNullOrWhiteSpace($postRegRep)) {
$newName = $newName -replace $postReg, $postRegRep;
}
$tgtList[$i] | Rename-Item -NewName $newName;
}
}
else {
continue;
}
Write-Host "Renaming done."
break;
}
function natualSort
{
PARAM(
[System.Collections.ArrayList]$Array,
[switch]$Descending
)
Add-Type -TypeDefinition @'
using System;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.InteropServices;
namespace NaturalSort {
public static class NaturalSort
{
[DllImport("shlwapi.dll", CharSet = CharSet.Unicode)]
public static extern int StrCmpLogicalW(string psz1, string psz2);
public static System.Collections.ArrayList Sort(System.Collections.ArrayList foo)
{
foo.Sort(new NaturalStringComparer());
return foo;
}
}
public class NaturalStringComparer : IComparer
{
public int Compare(object x, object y)
{
return NaturalSort.StrCmpLogicalW(x.ToString(), y.ToString());
}
}
}
'@
$Array.Sort((New-Object NaturalSort.NaturalStringComparer))
if($Descending)
{
$Array.Reverse()
}
return $Array
}
Write-Output "Templated Name Pattern`nExample: sample_file_{0:d2}.txt`td2 means 2 maximum padding zero's.`nDocumentation at https://ss64.com/ps/syntax-f-operator.html."
$template = Read-Host -Prompt "Masked template"
$dir = Read-Host -Prompt "Base directory containing files to rename"
if (![System.IO.Directory]::Exists($dir)) {
throw "Directory is invalid.";
}
$start = Read-Host -Prompt "Start from [default: 1]"
if ([string]::IsNullOrWhiteSpace($start)) {
$start = 1;
}
else {
$start = [int]$start;
}
$list = natualSort $(Get-ChildItem -LiteralPath $dir);
foreach ($item in $list) {
$item | Rename-Item -NewName ($template -f $start);
$start++
}
Write-Host "Renaming done."
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment