I have approximately 300 files, named in the format:
November Foo Bar And Stuff [Final Version].pdf
November Foo Bar And Stuff [Draft].pdf
November Lorum Ipsum [Final].pdf
November Lorum Ipsum [Draft].pdf`
They all start with “November “ and end with a bracketed word, but that word will vary slightly.
And I have approximately 150 corresponding directories in the format:
“Foo Bar And Stuff”
“Lorum Ipsum”
I would like to move the files in to folders with their associated names.
In other words,
- Search only for the string of text between “November “ and “[“
- Match the string in 1 against a list of directories
- When a match is found, move the file to the corresponding directory
- If no match is found, skip and continue to the next file
When complete, instead of a flat list of files, I should have all of my Foo Bar And Stuff related files in one directory, and my Lorum Ipsum files in another directory.
Let’s suppose that the files are in c:\files and the directories are in c:\directories
I tried moving these by hand in Explorer and it was tedious.
CodePudding user response:
Use Regex :
$filenames = @("November Foo Bar And Stuff [Final Version].pdf", "November Foo Bar And Stuff [Draft].pdf", "November Lorum Ipsum [Final].pdf", "November Lorum Ipsum [Draft].pdf")
$pattern = "(?<filename>November[^\[] )"
foreach($filename in $filenames)
{
$match = select-string $pattern -inputobject $filename
Write-Host '$match.Matches'
$match.Matches
Write-Host "filename = " $match.Matches.Value.Trim()
}
CodePudding user response:
You could do something like this:
$destination = 'C:\directories'
# because the files have square brackets in their name, use `-LiteralPath`
Get-ChildItem -LiteralPath 'C:\Files' -Filter 'November*.pdf' -File | ForEach-Object {
# filter the folder name from the file BaseName
$folderName = ($_.BaseName -replace '^November([^\[] ).*', '$1').Trim()
$targetFolder = Join-Path -Path $destination -ChildPath $folderName
if (Test-Path -Path $targetFolder -PathType Container) {
$_ | Move-Item -Destination $targetFolder -Force
}
}
To speed this up by not testing the existance of the target folder in every iteration, you could also first get a list of target directory names like so:
$destination = 'C:\directories'
$targets = (Get-ChildItem -Path $destination -Directory).Name
# because the files have square brackets in their name, use `-LiteralPath`
Get-ChildItem -LiteralPath 'C:\Files' -Filter 'November*.pdf' -File | ForEach-Object {
# filter the folder name from the file BaseName
$folderName = ($_.BaseName -replace '^November([^\[] ).*', '$1').Trim()
if ($targets -contains $folderName) {
$targetFolder = Join-Path -Path $destination -ChildPath $folderName
$_ | Move-Item -Destination $targetFolder -Force
}
}