File Output in Powershell without Extension
Pass the file name to the GetFileNameWithoutExtension
method to remove the extension:
Get-ChildItem "C:\Folder" | `
ForEach-Object { [System.IO.Path]::GetFileNameWithoutExtension($_.Name) } `
> C:\Folder\File.txt
I wanted to comment on @MatthewMartin's answer, which splits the incoming file name on the .
character and returns the first element of the resulting array. This will work for names with zero or one .
, but produces incorrect results for anything else:
file.ext1.ext2
yieldsfile
powershell.exe is good for me. Let me explain to thee..doc
yieldspowershell
The reason is because it's returning everything before the first .
when it should really be everything before the last .
. To fix this, once we have the name split into segments separated by .
, we take every segment except the last and join them back together separated by .
. In the case where the name does not contain a .
we return the entire name.
ForEach-Object {
$segments = $_.Name.Split('.')
if ($segments.Length -gt 1) {
$segmentsExceptLast = $segments | Select-Object -First ($segments.Length - 1)
return $segmentsExceptLast -join '.'
} else {
return $_.Name
}
}
A more efficient approach would be to walk backwards through the name character-by-character. If the current character is a .
, return the name up to but not including the current character. If no .
is found, return the entire name.
ForEach-Object {
$name = $_.Name;
for ($i = $name.Length - 1; $i -ge 0; $i--) {
if ($name[$i] -eq '.') {
return $name.Substring(0, $i)
}
}
return $name
}
The [String]
class already provides a method to do this same thing, so the above can be reduced to...
ForEach-Object {
$i = $_.Name.LastIndexOf([Char] '.');
if ($i -lt 0) {
return $_.Name
} else {
return $_.Name.Substring(0, $i)
}
}
All three of these approaches will work for names with zero, one, or multiple .
characters, but, of course, they're a lot more verbose than the other answers, too. In fact, LastIndexOf()
is what GetFileNameWithoutExtension()
uses internally, while what BaseName
uses is functionally the same as calling $_.Name.Substring()
except it takes advantage of the already-computed extension.
(ls).BaseName > C:\Folder\File.txt
Get-ChildItem "C:\Folder" | Select BaseName > C:\Folder\File.txt
And now for a FileInfo version, since everyone else beat me to a Path.GetFileNameWithoutExtension solution.
Get-ChildItem "C:\" | `
where { ! $_.PSIsContainer } | `
Foreach-Object {([System.IO.FileInfo]($_.Name)).Name.Split('.')[0]}