22

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
  • 1
    since I was looking for something a little different and Google landed me here: If someone is trying to only get files that don't have an extension, try Get-ChildItem $dir | ? {$_.Extension -ne ""} Commented Jun 23, 2016 at 15:26

5 Answers 5

26
Get-ChildItem "C:\Folder" | Select BaseName > C:\Folder\File.txt
Sign up to request clarification or add additional context in comments.

4 Comments

Thank you for the quick reminder. I could not remember BaseName for the life of me. I ended up using: Get-ChildItem "C:\Folder" | Foreach-Object {$_.BaseName} > C:\Folder\File.txt
@CaptHowdy $foo | Get-Member will reveal the properties and methods of an object.
If someone is looking for the shorthand version for current directory, try this ls . | Select BaseName.
I wish I could fave @ansgar-wiechers' comment, I always seem to forget about Get-Member!
4

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 yields file
  • powershell.exe is good for me. Let me explain to thee..doc yields powershell

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.

Comments

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]}

2 Comments

Exactly what I needed, files I had also had some numbers appended to it. having .split('.') helped me cut off everything that was appended including ext.
It should be noted that removing an extension involves returning everything before the last . whereas this will return everything before the first .. For names that contain zero or one . (such as in the question) there is no difference, but for names like file.ext1.ext2 and powershell.exe is good for me. Let me explain to thee..doc it returns file and powershell, respectively. I have updated my answer with a few approaches to fix this. By the way, [System.IO.FileInfo]($_.Name)).Name is redundant and can be reduced to $_.Name.
3
(ls).BaseName > C:\Folder\File.txt

1 Comment

Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.
1

Use the BaseName property instead of the Name property:

Get-ChildItem "C:\Folder" | Select-Object BaseName > C:\Folder\File.txt

1 Comment

you should probably explain why: Basename gives file name without extension. Name property contains extension.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.