问题
Here is what I have so far:
Get-ChildItem "C:\Folder" | Foreach-Object {$_.Name} > C:\Folder\File.txt
When you open the output from above, File.txt, you see this:
file1.txt
file2.mpg
file3.avi
file4.txt
How do I get the output so it drops the extension and only shows this:
file1
file2
file3
file4
Thanks in advance!
EDIT
Figured it out with the help of the fellows below me. I ended up using:
Get-ChildItem "C:\Folder" | Foreach-Object {$_.BaseName} > C:\Folder\File.txt
回答1:
Get-ChildItem "C:\Folder" | Select BaseName > C:\Folder\File.txt
回答2:
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.ext2yieldsfilepowershell.exe is good for me. Let me explain to thee..docyieldspowershell
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.
回答3:
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]}
回答4:
Use the BaseName property instead of the Name property:
Get-ChildItem "C:\Folder" | Select-Object BaseName > C:\Folder\File.txt
来源:https://stackoverflow.com/questions/13370055/file-output-in-powershell-without-extension