1

this is my first stack question so go easy on me.

Currently working on a project to create a new folder on a network drive by incrementing off of the previous folders version number.

For example: 5.2.0.0110 -> 5.2.0.0111

Here is my current powershell solution that does the trick:

$SourceFolder = "\\corpfs1\setup\ProtectionSuite\Version 5.2.0.x\5.2.0.0001"
$DestinationFolder = "\\corpfs1\setup\ProtectionSuite\Version 5.2.0.x"
$msiSourceFolder = "\\SourceMsiPath"
$exeSourceFolder = "\\SourceExePath"
if (Test-Path $SourceFolder)
{
        $latest = Get-ChildItem -Path $DestinationFolder| Sort-Object Name -Descending | Select-Object -First 1 
        #split the latest filename, increment the number, then re-assemble new filename:
        $newFolderName = $latest.BaseName.Split('.')[0] + "." + $latest.BaseName.Split('.')[1] + "."+ $latest.BaseName.Split('.')[2] + "." + ([int]$latest.BaseName.Split('.')[3] + 1).ToString().PadLeft(4,"0")
        New-Item -Path $DestinationFolder"\"$newFolderName -ItemType Directory

        Copy-Item $msiSourceFolder -Destination $DestinationFolder"\"$newFolderName
        Copy-Item $exeSourceFolder -Destination $DestinationFolder"\"$newFolderName
}

However, one thing that this does not account for is version numbers with string at the end. This solution attempts to covert the string -> int which fails. Some of the folders have strings as they are for internal releases so there is no way to just change my naming semantics.

For example: 5.2.0.1234 (eng) -> 5.2.0.1235

I would like to ignore any text after the last four digits and increment as shown in the example above. If anyone has a suggestion I am all ears! Thank you.

mklement0
  • 382,024
  • 64
  • 607
  • 775
tunamaster
  • 11
  • 2

2 Answers2

1

Assuming that your folder names contain only one 4-digit sequence preceded by a ., it is simpler to match and replace only it, using the regular-expression-based -replace operator with a script block-based substitution:

Update:

  • A later clarification revealed that the post-version suffix in the input string should be (b) removed from the output rather than (a) just ignored for the purpose of incrementing while getting preserved in the output - see the bottom section for a solution to (b).

SOLUTION (a): If the post-version suffix should be preserved:

In PowerShell (Core) v6.1+:

# Replace the sample value '5.2.0.1234 (eng)' with the following in your code:
#   $newFolderName = $latest.BaseName [-replace ...]
'5.2.0.1234 (eng)' -replace '(?<=\.)\d{4}', { '{0:0000}' -f  (1 + $_.Value) }

The above yields 5.2.0.1235 (eng) - note the incremented last version-number component and the preservation of the suffix.

In Windows PowerShell (versions up to 5.1), where script block-based substitutions aren't supported, direct use of the underlying .NET API is required:

[regex]::Replace('5.2.0.0110 (eng)', '(?<=\.)\d{4}', { '{0:0000}' -f  (1 + $args[0].Value) })

Explanation:

  • (?<=\.)\d{4} is a regex (regular expression) that matches a literal . (\.) inside a look-behind assertion ((?<=...)), followed by 4 ({4}) digits (\d). The look-behind assertion ensures that the literal . isn't included in the text captured by the match.

  • The script block ({ ... }) receives information about (each) match, as a System.Text.RegularExpressions.Match instance, via the automatic $_ variable in the PowerShell (Core) solution, via the automatic $args variable in the Windows PowerShell solution with the direct .NET call.

  • The script block's output (return value) is used to replace the matched text:

    • '{0:0000}' -f ... uses -f, the format operator, to format the RHS with 4-digit 0-padding.

    • (1 + $_.Value) / (1 + $args[0].Value) adds 1 to the 4-digit sequence captured by the match, which is implicitly converted to a number due to the LHS of the + operation being a number.


SOLUTION (b): If the post-version suffix should be removed:

In PowerShell (Core) v6.1+:

'5.2.0.1234 (eng)' -replace '\.(\d{4}).*', { '.{0:0000}' -f  (1 + $_.Groups[1].Value) }

The above yields 5.2.0.1235 - note the incremented last version-number component and the absence of the suffix.

In Windows PowerShell:

[regex]::Replace('5.2.0.1234 (eng)', '\.(\d{4}).*', { '.{0:0000}' -f  (1 + $args[0].Groups[1].Value) })
mklement0
  • 382,024
  • 64
  • 607
  • 775
1

You can do:

$version = ($latest.BaseName -replace '^((?:\d+\.){3}\d{4}).*', '$1').Split('.')
$version[-1] = '{0:D4} -f ([int]$version[-1] + 1)
$newFolderName = $version -join '.'

# '5.2.0.0110 (eng)' --> '5.2.0.0111'

As per your comment, you should use Join-Path for constructing the full target path:

$targetPath = Join-Path -Path $DestinationFolder -ChildPath $newFolderName
$null = New-Item -Path $targetPath -ItemType Directory -Force

Copy-Item $msiSourceFolder -Destination $targetPath
Copy-Item $exeSourceFolder -Destination $targetPath
Theo
  • 57,719
  • 8
  • 24
  • 41
  • Ok, this seems good. However, the formatting is a bit off. It should be incremented and keep the four digits after the last ".". Could you point me in the right direction for making that edit? Thank you for your response, Theo. – tunamaster May 20 '21 at 16:28
  • @tunamaster I see what you mean now. Updated the answer. – Theo May 20 '21 at 17:16
  • The '(eng)' suffix does not need to be preserved. Some of the folders have the suffix, but they are added manually. This is why when incrementing things got screwy. – tunamaster May 20 '21 at 18:04
  • @Theo, this is just about right, however, I am getting an error from the $version[-1] line. It is stating that "New item : The given paths format is not supported"... any ideas? – tunamaster May 20 '21 at 18:28
  • @tunamaster That is because of the way you construct the full pathname from it. use `New-Item -Path (Join-Path -Path $DestinationFolder -ChildPath $newFolderName) -ItemType Directory -Force` instead – Theo May 20 '21 at 18:32
  • @tunamaster Please see the edited answer about that – Theo May 20 '21 at 18:40
  • Strange, I am still presented with the same error message. I have verified the way in which my pathname is constructed and it seems to obey the proper naming convention. I cannot seem to debug this successfully. Perhaps this should not be null as a folder is being produced? Forgive my ignorance, I am not well versed with power shell... – tunamaster May 20 '21 at 19:01
  • 1
    @tunamaster You need to specify the actual file or folder you want to copy. Right now, your code defines the source paths as just `\\servername`, so without the share and path to whatever you need to copy. This is incomplete, hence the error. /// BTW your question is about capturing and incrementing a folder name, not about other mistakes that might be in the code.. – Theo May 20 '21 at 19:10
  • @tunamaster Oh yes, the `$null` is just there to avoid unnecessary console output, nothing more. It does not 'nullify' the folder created or anything. – Theo May 20 '21 at 19:17
  • Sorry, in my actual code I have the full paths listed. These were just placeholders for this post. Therefore, I believe there is something else going on here. All other aspects of the code work. PS is presenting an error at the line in which the new folder is created. I have included the full paths now. Could the error from from the space in "version 5.2.0.xxxx" when joining the paths? – tunamaster May 20 '21 at 19:17
  • @tunamaster You never showed the folder name had `'version '` in front of the numbers.. The example only showed there could be an **appended** string like `' (eng)'`. If that is the case, remove the `^` in the replace regex on the very first line of my code. After the creation of `$targetPath`, add a line `Write-Host $targetPath` so you can see what the path looks like. – Theo May 20 '21 at 19:27
  • 1
    @tunamaster I'm on mobile now, but Please edit your question and give **real** examples of foldernames to increment and matching examples of what is expected as new folder names. I get the distinct feeling you are keeping a lot if information hidden right now, so after each solution you come up with a new (unmentioned before) problem with the code. As I said earlier, your question is about **capturing and incrementing** a foldername that could have text appended. My answer solves that, so does mklement0 's answer. – Theo May 20 '21 at 19:35
  • Got it, thanks for your help. Also it should be noted that the directory with the 'version' in it is not the folder which is being incremented. That is the directory which contains all the subfolders with the incremented number, not the folder itself. Hence it is the destination folder. Therefore, the examples I provided are what would be incremented. Again, thanks for your help. – tunamaster May 20 '21 at 19:38