diff --git a/README.md b/README.md index 622db2b..97e5764 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,13 @@ -# tarotfilenamer +# Tarot File Renamer -A PowerShell script that takes a directory of scanned tarot cards and organizes them into directories. \ No newline at end of file +A PowerShell script that takes a directory of scanned tarot cards and organizes them into directories. + +Start with a directory of **at least** 22 trump cards, along with 14 cards each in four suits. If your deck has more than 22 trumps, just make sure the card names are included in the `$trumps` array. + +The script will prompt you to provide the suit names and court card names, if they vary from the standard. + +The script auto-rotates each image. If you don't need this, comment out + +```ps +$img.RotateFlip("Rotate90FlipNone") +``` \ No newline at end of file diff --git a/organizer.ps1 b/organizer.ps1 new file mode 100644 index 0000000..eacfbc3 --- /dev/null +++ b/organizer.ps1 @@ -0,0 +1,370 @@ +# tarot folder +$tdir = $env:OneDrive + "\Projects\Tarot\Scans" + +# empty array to hold menu options for user interaction +$menuOpts = @{}; + +# retrieve list of decks (folders) in $tdir +$decks = Get-ChildItem -path $tdir -Directory + +Write-Host = "==================== Scanned Decks ====================" + +# for each deck, create a new menu item +for ($d = 0; $d -lt $decks.Count; $d++) { + Write-Host "[$d] $($decks[$d].Name)" + $menuOpts.Add($d, $decks[$d]) +} + +# ask user which directory to use +[int]$selOpt = Read-Host "Select a deck directory" +$theOpt = $menuOpts.Item($selOpt) + +Write-Host "" + +# if directory contains no files, check for directories +$files = Get-ChildItem -Path $theOpt.FullName -File +$dirs = Get-ChildItem -Path $theOpt.FullName -Directory + +if ($null -eq $files -and $null -eq $dirs) { + # nothing useful found, die + Write-Host "The selected deck directory has no files or folders. Try again." + end; +} +else { + # initialize string arrays + $trumps = @( + "The Fool", + "The Magician", + "The High Priestess", + "The Empress", + "The Emperor", + "The Hierophant", + "The Lovers", + "The Chariot", + "Strength", + "The Hermit", + "The Wheel of Fortune", + "Justice", + "The Hanged Man", + "Death", + "Temperance", + "The Devil", + "The Tower", + "The Star", + "The Moon", + "The Sun", + "Judgememt", + "The World" + ) + + $trumps = @( + "The Fool", + "The Magician", + "The High Priestess", + "The Empress", + "The Emperor", + "The Hierophant", + "The Lovers", + "The Chariot", + "Strength", + "The Hermit", + "The Wheel of Fortune", + "Justice", + "The Hanged Man", + "Death", + "Temperance", + "The Devil", + "The Tower", + "The Star", + "The Moon", + "The Sun", + "Judgememt", + "The World", + "The Well", + "The Artist" + ) + + $suits = @( + "Cups", + "Pentacles", + "Swords", + "Wands" + ) + + $numbers = @( + "Ace", + "Two", + "Three", + "Four", + "Five", + "Six", + "Seven", + "Eight", + "Nine", + "Ten" + ) + + $courts = @( + "Page", + "Knight", + "Queen", + "King" + ) + + $trumpcount = $trumps.Count + $trumpend = $trumpcount - 1 + $cardcount = $trumps.Count + 56 + + $npath = $theOpt.FullName + + if ($null -eq $files -and $null -ne $dirs) { + # here be directories + Write-Host "The selected deck directory contains folders." + + # make sure there's exactly five directories + # major arcana plus four suits + if ($dirs.Count -ne 5) { + Write-Host "Directory must have exactly five directories. Fix and try again." + } + else { + # we have five directories + # use existing directory name + + # if directory contains 22 cards, it's 00 + # if directory contains 14 cards, it's 01..04 + # everything else is ignored + + $suitindex = 1 + + foreach($dir in $dirs) { + $numfiles = ($dir | Get-ChildItem | Measure-Object).Count + + $dirname = $dir.Name + + if ($numfiles -eq $trumpcount) { + # major arcana + $newdir = $dir.Parent.FullName + "\00 - $dirname" + + # get list of images + $cards = $dir | Get-ChildItem + + # for each of 22 images, go through the list of card names + foreach($t in 0..$trumpend) { + # get the file + $file = $cards[$t] + + # set new filename e.g. 00.00 - The Fool + $base = $t.ToString().PadLeft(2,'0') + $card = $trumps[$t] + $new = "00" + "." + $base + " - " + $card + ".jpg" + + $newname = $dir.FullName + "\" + $new + + if ($file.Name -eq $new) { + # this file has already been processed and named. + continue + } + else { + # rename the image to the standard format + Rename-Item $file.FullName -NewName $newname + } + } + + # rename directory + Rename-Item $dir.FullName -NewName $newdir + } + elseif ($numfiles -eq 14) { + # suits + + # suit name is folder name + $suitname = $dir.Name + + # get the number, e.g. 01 + $suitnum = $suitindex.ToString().PadLeft(2,"0") + + # set the new folder name + $newdir = $dir.Parent.FullName + "\$suitnum - $suitname" + + # get the cards + $cards = $dir | Get-ChildItem + + # loop through cards range + foreach($i in 0..13) { + # get the file + $file = $cards[$i] + + $card = $fullsuit[$i] + " of " + $suitname + + # set new filename e.g. 00.00 - The Fool + $base = ($i + 1).ToString().PadLeft(2,'0') + $new = $suit + "." + $base + " - " + $card + ".jpg" + + $newname = $dir.FullName + "\" + $new + + if ($file.Name -eq $new) { + # this file has already been processed and named. + continue + } + else { + # save the changes + Rename-Item $file.FullName -NewName $newname + } + } + + # rename directory + Rename-Item $dir.FullName -NewName $newdir + + # add one to the suit index + $suitindex++ + } + else { + Write-Host "Directory $($dir.Name) must have exactly 14 or 22 cards. Fix and try again." + break; + } + } + + } + } + elseif ($null -ne $files) { + # set up variables + $suitsin = Read-Host "Enter a comma-separated list of four suit names. List will be processed in order. Default is Cups,Pentacles,Swords,Wands" + + $courtsin = Read-Host "Enter a comma-separated list of four court names. List will be processed in order. Default is Page,Knight,Queen,King" + + if ($suitsin -ne "") { + $suits = $suitsin.Split(",").Trim() + } + + if ($courtsin -ne '') { + $courts = $courtsin.Split(",").Trim() + } + + $fullsuit = $numbers + $courts + + # here be files + Write-Host "The selected deck directory contains files." + + # get file types + $exts = $files.Extension | group + + if ($exts.Count -ne $cardcount.ToString()) { #-or ($exts | % { $_.Count } ).Contains(78)) { + Write-Host "Directory must have exactly 78 cards. Fix and try again." + break; + } + elseif ($exts.Length -ne 1) { + Write-Host "More than one file type found. All files must be the same type." + break; + } + elseif ((".JPG,.PNG").Contains($exts.Name)) { + Write-Host "$cardcount images identified." + Write-Host "The first $trumpcount cards must be the trumps in order, Fool first." + + # Create folders + $newpath = $npath + "\00 - Major Arcana" + + New-Item -Path $newpath -ItemType Directory + + # load .NET image assembly + [System.Reflection.Assembly]::LoadWithPartialName("System.Drawing") + + # rename first 22 cards + foreach ($t in 0..$trumpend) { + # get the file + $file = $files[$t] + + # set new filename e.g. 00.00 - The Fool + $base = $t.ToString().PadLeft(2,'0') + $card = $trumps[$t] + $new = "00" + "." + $base + " - " + $card + ".jpg" + + if ($file.Name -eq $new) { + # this file has already been processed and named. + continue + } + else { + # create an image from the file + $img = [System.Drawing.Image]::FromFile($file.FullName) + + # if the image name starts with PD_ it's new, so rotate + if ($file.Name.StartsWith("PD_")) { + # rotate the image 90 degrees + $img.RotateFlip("Rotate90FlipNone") + } + + $newname = $newpath + "\" + $new + + # save the changes + $img.Save($newname,"jpeg") + + #$file.Delete() + } + } + + Write-Host "" + + if ($suits.Length -eq 4) { + # exactly four suits, proceed + foreach ($s in 0..3) { + # filename and folder base is 01,02,03,04 + $suiti = $s + 1 + $suit = $suiti.ToString().PadLeft(2,"0") + + $suitname = $suits[$s] + + $spath = $theOpt.FullName + "\$suit - $suitname" + + New-Item -Path $spath -ItemType Directory + + # start at index after last trump ($trumpcount) + # add 14 x $s to 22 for start index + # add 13 to above for end index + $start = $trumpcount + (14 * $s) + $end = $start + 13 + + # pull out the files to be renamed + $tempfiles = $files[$start..$end] + + # loop through identified range + foreach($i in 0..13) { + # get the file + $file = $tempfiles[$i] + + $card = $fullsuit[$i] + " of " + $suitname + + # set new filename e.g. 00.00 - The Fool + $base = ($i + 1).ToString().PadLeft(2,'0') + $new = $suit + "." + $base + " - " + $card + $exts[0].Name + + if ($file.Name -eq $new) { + # this file has already been processed and named. + continue + } + else { + # create an image from the file + $img = [System.Drawing.Image]::FromFile($file.FullName) + + # if the image name starts with PD_ it's new, so rotate + if ($file.Name.StartsWith("PD_")) { + # rotate the image 90 degrees + $img.RotateFlip("Rotate90FlipNone") + } + + $newname = $spath + "\" + $new + + # save the changes + $img.Save($newname,"jpeg") + + #$file.Delete() + } + } + } + } + else { + # four suits required + Write-Host "Please enter exactly four suits, separated with commas." + Write-Host "For example: Cups,Pentacles,Swords,Wands" + break; + } + } + } +} \ No newline at end of file