Cataster
Cataster

Reputation: 3551

How do I strip part of a file name?

Suppose I have a file database_partial.xml.

I am trying to strip the file from "_partial" as well as extension (xml) and then capitalize the name so that it becomes DATABASE.

Param($xmlfile)

$xml = Get-ChildItem "C:\Files" -Filter "$xmlfile"

$db = [IO.Path]::GetFileNameWithoutExtension($xml).ToUpper()

That returns DATABASE_PARTIAL, but I don't know how to strip the _PARTIAL part.

Upvotes: 1

Views: 457

Answers (2)

mklement0
mklement0

Reputation: 440297

Ansgar Wiechers's helpful answer provides an effective solution.

To focus on the more general question of how to strip (remove) part of a file name (string):

Use PowerShell's -replace operator, whose syntax is:
<stringOrStrings> -replace <regex>, <replacement>:

  • <regex> is a regex (regular expression) that matches the part to replace,
  • <replacement> is replacement operand (the string to replace what the regex matched).
    • In order to effectively remove what the regex matched, specify '' (the empty string) or simply omit the operand altogether - in either case, the matched part is effectively removed from the input string.

For more information about -replace, see this answer.

Applied to your case:

$db = 'DATABASE_PARTIAL' # sample input value

PS> $db -replace '_PARTIAL$', ''  # removes suffix '_PARTIAL' from the end (^)
DATABASE

PS> $db -replace '_PARTIAL$'      # ditto, with '' implied as the replacement string.
DATABASE

Note:

  • -replace is case-insensitive by default, as are all PowerShell operators. To explicitly perform case-sensitive matching, use the -creplace variant.

  • By contrast, the [string] type's .Replace() method (e.g., $db.Replace('_PARTIAL', ''):

    • matches by string literals only, and therefore offers less flexibility; in this case, you couldn't stipulate that _PARTIAL should only be matched at the end of the string, for instance.
    • is invariably case-sensitive in the .NET Framework (though .NET Core offers a case-insensitive overload).

Building on Ansgar's answer, your script can therefore be streamlined as follows:

Param($xmlfile)

$db = ((Get-ChildItem C:\Files -Filter $xmlfile).BaseName -replace '_PARTIAL$').ToUpper()

Note that in PSv3+ this works even if $xmlfile should match multiple files, due to member-access enumeration and the ability of -replace to accept an array of strings as input, the desired substring removal would be performed on the base names of all files, as would the subsequent uppercasing - $db would then receive an array of stripped base names.

Upvotes: 1

Ansgar Wiechers
Ansgar Wiechers

Reputation: 200493

You don't need GetFileNameWithoutExtension() for removing the extension. The FileInfo objects returned by Get-ChildItem have a property BaseName that gives you the filename without extension. Uppercase that, then remove the "_PARTIAL" suffix. I would also recommend processing the output of Get-ChildItem in a loop, just in case it doesn't return exactly one result.

Get-ChildItem "C:\Files" -Filter "$xmlfile" | ForEach-Object {
    $_.BaseName.ToUpper().Replace('_PARTIAL', '')
}

If the substring after the underscore can vary, use a regular expression replacement instead of a string replacement, e.g. like this:

Get-ChildItem "C:\Files" -Filter "$xmlfile" | ForEach-Object {
    $_.BaseName.ToUpper() -replace '_[^_]*$'
}

Upvotes: 2

Related Questions