locked
PowerShell to delete all files but 1 in a dir? RRS feed

  • Question

  • I'm trying to delete all but one .txt files in each folder of a directory tree. The number of the .txt files varies in each subdirectory, and so do the names. Some subdirectories have five .txt files in them, and some have only one. If the folder has only one .txt file, it needs to stay there. I the folder has more than one .txt file in it, then all others but one need to be deleted. It doesn't matter which .txt file is kept. I just need the rest to be deleted. I've tried various versions of "get-content" or "get-childitem" or "measure-object", but I'm not having any luck.  Anyone smarter than me have an idea how to approach this? Thank you.




    • Edited by ScriptWork Thursday, June 1, 2017 3:32 PM further clarification
    Thursday, June 1, 2017 1:45 PM

Answers

  • To build on what the others has already said, what you need to do:

    Get the folders that you want to clear the files in

    Loop through them and remove all but one file

    Should look something like this (I tried it and it worked):

    $folders = Get-ChildItem c:\temp\test -Recurse -Directory
    foreach($folder in $folders.fullname){
        Write-Host "Clearing in $folder"
        Get-ChildItem -Path $folder -Filter '*.txt' | Select-Object -Skip 1 | Remove-Item
    }

    • Marked as answer by ScriptWork Friday, June 2, 2017 1:56 PM
    Friday, June 2, 2017 6:51 AM

All replies

  • Hello,

    let's say: This is quite simple. You'll only need Remove-Item cmdlet and use it like this

    Remove-Item "Path\*"

    to delete all files in <Path>. To exclude files from this selection, use parameter -Exclude. But of course, you need a definition how this file looks like.

    I don't see any reason for using Measure-Object here. I think, you should learn some Powershell basics first. 

    Good luck

    Christoph


    • Edited by hpotsirhc Thursday, June 1, 2017 1:54 PM
    Thursday, June 1, 2017 1:53 PM
  • Thanks for your reply. Your example will simply remove all files. I need to leave one file in each dir, and if there is only one file in a dir, then it needs to stay there. Perhaps I didn't make that clear. Sorry about that.

    I was playing with Measure-Object to count files, like the following: Get-ChildItem -Path f:\temp -Recurse -File | Measure-Object | %{$_.Count}. I thought that may be step 1: count the files.


    Thursday, June 1, 2017 2:37 PM
  • Get-ChildItem -Filter '*.txt' | Select-Object -Skip -First 1 | Remove-Item


    Grüße - Best regards

    PS:> (79,108,97,102|%{[char]$_})-join''

    Thursday, June 1, 2017 2:59 PM
  • Thank you, I really appreciate the attempt, but that doesn't work either.
    Thursday, June 1, 2017 3:17 PM
  • Get-ChildItem -Path "C:\Temp\*\" -Filter '*.txt' -Recurse | Select-Object -Skip 1 | Remove-Item

    The above will work for the first directory it sees. All other directories have all .txt files removed, however. I'm trying to leave behind one .txt file in each directory. 

    Thursday, June 1, 2017 3:25 PM
  • So you should collect first all directories you wish to treat and then run this command foreach collected directory but without the -recurse parameter.

    Grüße - Best regards

    PS:> (79,108,97,102|%{[char]$_})-join''


    • Edited by BOfH-666 Thursday, June 1, 2017 3:50 PM
    Thursday, June 1, 2017 3:49 PM
  • To build on what the others has already said, what you need to do:

    Get the folders that you want to clear the files in

    Loop through them and remove all but one file

    Should look something like this (I tried it and it worked):

    $folders = Get-ChildItem c:\temp\test -Recurse -Directory
    foreach($folder in $folders.fullname){
        Write-Host "Clearing in $folder"
        Get-ChildItem -Path $folder -Filter '*.txt' | Select-Object -Skip 1 | Remove-Item
    }

    • Marked as answer by ScriptWork Friday, June 2, 2017 1:56 PM
    Friday, June 2, 2017 6:51 AM
  • That's a prettier solution than what I came up with, and it works perfectly. Thank you!
    Friday, June 2, 2017 1:55 PM