Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Powershell Move Most recent File

I have a directory lets call it C:\MoveFile within this directory are thousands of files similarly named

  • Name Date Modified
  • Dog_123123_Grey.doc 18/11/2015
  • Dog_123123_Grey (2).doc 19/11/2015
  • Dog_123123_Grey (3).doc 17/11/2015
  • Cat_123123_Blue (3).doc 01/01/2015
  • Cat_123123_Pink (6).doc 07/04/2015
  • Cat_123123_Pink (7).doc 10/04/2015

Now if the version number in the file name was consistently numbered (2) etc it would be easy, however what I want to do is have powershell run through the items in the directory and move the most recent file based on the date modified to a new file location so that from the list provided the new directory will contain.

Name Date Modified

  • Dog_123123_Grey (2).doc 19/11/2015
  • Cat_123123_Blue (3).doc 01/01/2015
  • Cat_123123_Pink (7).doc 10/04/2015

Now as far as my head can get with this is,

gci C:\MoveFile\*.doc | sort LastWriteTime -desc | select -first 1 | cpi -dest c:\NewDirectory

Which I haven't tested as I know its not complete and will not do what I need it to do, being honest there I know that somehow I need to ignore anything that is in the brackets e.g. (3) which I don't know how to do. I had considered looking at 'somehow' only looking at the first 15 digits but some of the file names may be longer or shorter than this.

Scratching my head in frustration, anyone with more experience than I have any ideas?

like image 930
Mr Deans Avatar asked Nov 22 '25 06:11

Mr Deans


2 Answers

If I understand your need correctly, here is a script that will help you list the files to move (PS 3.0 needed for the -File parameter of Get-ChildItem).

Here I create a new Group property in which I remove the "version number" to obtain a kind of "key" to group the items.

I list the files, sort them by descending LastWriteTime, and then group them by Group and take the first item of each group.

$sourceFolder = "C:\MoveFile"

$files = Get-ChildItem $sourceFolder -File |
    Sort-Object LastWriteTime -Descending |
    Select-Object *,@{ n = "Group"; e = { $_.Name -replace "\s\(\d+\)","" } }

$filesToMove = $files | Group-Object Group | % {
    $_.Group | Select-Object -First 1
}

$filesToMove | Select-Object Name,LastWriteTime
like image 115
sodawillow Avatar answered Nov 23 '25 22:11

sodawillow


What you might want to do is:

  1. Group files by name (excluding the version in the filename)
  2. Sort the files in each group individually
  3. Pick the most recent from each group

To get the filename without the version number, we can use the -replace regex operator to remove any set of parentheses containing one or more digits at the end of the BaseName string (the filename exlcuding the file extension):

PS C:\> 'Cat_123123_Blue (3)' -replace '\(\d+\)$',''
Cat_123123_Blue

So, to group them by this string, we do:

$FileGroups = Get-ChildItem -Path C:\Movefile\ -Filter *.doc |Group-Object { ($_.BaseName -replace '\(\d+\)$','').Trim() }

Then iterate over our array of groups:

$FileGroups |ForEach-Object { 
    # Sort each group, grab the most recent file
    $RecentFile = $_.Group |Sort-Object LastWriteTime -Descending |Select -First 1 # Copy it
    Copy-Item $RecentFile.FullName -Destination C:\NewFolder\
} 
like image 20
Mathias R. Jessen Avatar answered Nov 23 '25 22:11

Mathias R. Jessen



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!