Using Windows Power Automate Desktop to move plots

Hey all, I thought I’d share a novel way to move completed plots to your network drives. I know there are scripts for this but I gave myself the challenge of learning a new tool - Power Automate Desktop! If you’ve used Microsoft Flow (or any “if this then that” type of cloud connector service) then this will be quite natural for you.

The benefits of this flow are as follows:

  • The plotter doesn’t have to wait for the network copy operation. It writes to a local destination folder that this flow is watching and then moves on to start the next plot.
  • The files are moved ONE AT A TIME to the network destination drives. If you’ve ever watched multiple plotter instances try to move a file across the network at the same time, you know this pain. This flow will move the finished files in serial instead of parallel - this gets plots to your farmer faster. (e.g. Instead of taking 30 minutes to move 2 plots simultaneously, it now takes 15 min to move the first one and start farming it immediately, then 15 min to move the second one.)
  • The flow will upload the plot to the drive with the most free space.

This flow assumes you have a target shared network directory that contains a list of subdirectories. Each of these subdirectories should be mapped to your physical storage drives. Here’s my “StoragePool” folder on the server:

image

Notice that I name each folder with the serial number of the attached drive - this makes it easy to find the physical drive later if needed. Also note that all my drives are full except for the last two at the bottom. Ideally, we’d like our flow to be smart about where it moves our plots. It should always move a new plot to the drive with the most space free. This way the plots are balanced over all drives.

Tip for getting those cool size columns in Windows Explorer

Right-click the column headers in Windows Explorer, choose “More…” and add the Size, Space Free and Space Used columns.

It should also rename the extension of the plot file before moving it, then rename it back to the original name once it has finished moving. This way we avoid any errors in the Chia UI about bad plot files.

So here’s my solution! Unfortunately there isn’t a simple way to share these Flows yet since it is still in “Preview” but it shouldn’t take much time to recreate from this screenshot. Have some fun and learn something new - feel free to ask questions about why I did something a certain way or make suggestions if you have a better way to accomplish the same task!

Download Power Automate Desktop from here: Power Automate For Desktop | Microsoft Power Automate

4 Likes

Updates! Here is the latest version of the Power Automate flow that I’m using after I’ve learned some new things:

  • Instead of the hacky loop on line 15 to find the lowest file count folder, now I just sort the list of subfolders by file count in step 11.
  • The Move file step 14 has error handling (the little shield icon on the left). If you open up that step, you’ll see that on an error, we GoTo the “TryNextSubFolder” label, which continues the loop. If we don’t have an error, we will Exit the loop. If there is an error when we try to move the file to the destination (e.g. not enough free space) then we will continue on to the next folder.

This has been running on my 4 plotters for the last day or so and seems to work great!

4 Likes

Thanks for sharing. From a cursory first reading, I’m unclear as to the exact advantages of this over straight robocopy.

This “flow” intelligently distributes the plots to the drive with the most free space available. It could also be modified to always fill up a destination drive before moving on to the next destination drive by just reversing the sort in step 12. I don’t think pure robocopy can do that?

Assume you have a network share and you have mounted 20 or so drives as folders under that network share. By pointing this script at the share, it will pick up finished plots and it will send them to the subfolder (drive) with the most (or least) free space.

The other interesting possibility is to set up a target “drop” share on the server (preferably an SSD if you have multiple plotters sending plots) and then just point all your plotters to the drop. Now run this “flow” on the server and have it watch the share. It could then distribute the plots out onto your drives automatically - this way you keep your plotters “dumb” and they just send everything to the share. I do like having my plotters plot to a local drop drive though - this way they can immediately move on to the next plot instead of waiting for the network transfer.

Again, all of this can be done with scripting of almost any sort, but not pure robocopy as far as I know. I just thought it was interesting to learn Yet Another Scripting Tool :sunglasses:

Thanks for clarifying. I just have robocopy pick up my plots form my single staging place to my single final place, so I missed the nuances of multiple locations.

1 Like

This is just genius. I was unaware of this software. I used to use Automate (from helpsystems). Used to be NetworkAutomation. But very similar to this. I just set this up to move my plots after MadMax finishes them. That way MadMax can start on a new plot instead of just sitting there waiting for the file to upload to the NAS. Saved me a bunch of time.

And thank you for posting your workflow. I would have figured it out, but that saved me a couple of hours of tinkering.

1 Like

Cool! It would be very easy to set up something using this to delete old (non-pooling) plots as new ones are created! I think I will put something like that together for when pools come out!

1 Like

Yeh, shouldn’t be too hard. Just set a date variable. Then any plot file with a creation date before that date is a non-portable plot that can be deleted and replaced.

Exactly what I was thinking

I just finished reworking my workflow script. Now it does the following:

  • Determines what system it is (which plotter)
  • Creates a list of all destination drives (currently 20)
  • Using the system name, it determines what destination IP to use (so two plotters don’t send on the same connection)
  • Checks to see if there is a plot ready to be send.
  • Pulls the plot file size
  • Runs through each destination drive and checks to see if there is room for the new file and if there is not already a tmp file there (meaning another system is already moving a file there). If there is not room or if there is already a tmp file, that destination is skipped.
  • When it finds a suitable destination drive, begin the move.
  • It also logs to a local text file when the move is started and finished.
    When the cycle is started each time, it shuffles the destination drive list.

Now that I have this setup. When portable plots are ready, I can just modify this to look for older plot files, delete and then move.

2 Likes

Thanks for telling us about this great technique! Would you be willing to share your flow file?

Yep sure - I found that you can just copy/paste directly into/out of notepad! So copy this and then make a new flow and just paste it into the editor - it should recreate all the steps! Change SourceDirectory and TargetDirectory of course.

You can also Ctrl-A to select all of your steps and copy and then paste to notepad if you want to share your flow with somebody else.

Here’s the latest that I’m using:

SET SourceDirectory TO $'''T:\\'''
SET TargetDirectory TO $'''\\\\DESKTOP-1234567\\StoragePool\\'''
LABEL CheckForNewFiles
Folder.GetFiles Folder: SourceDirectory FileFilter: $'''*.plot;*.moving''' IncludeSubfolders: False FailOnAccessDenied: True SortBy1: Folder.SortBy.NoSort SortDescending1: False SortBy2: Folder.SortBy.NoSort SortDescending2: False SortBy3: Folder.SortBy.NoSort SortDescending3: False Files=> PlotFiles
IF PlotFiles.Count = 0 THEN
    WAIT 60 
ELSE
    LOOP FOREACH CurrentPlotFile IN PlotFiles
        Folder.GetSubfolders Folder: TargetDirectory FolderFilter: $'''*''' IncludeSubfolders: False FailOnAccessDenied: False SortBy1: Folder.SortBy.NoSort SortDescending1: False SortBy2: Folder.SortBy.NoSort SortDescending2: False SortBy3: Folder.SortBy.NoSort SortDescending3: False Subfolders=> TargetSubDirectories
        Variables.SortListByProperty List: TargetSubDirectories Property1: $'''FilesCount''' SortDirection1: Variables.SortDirection.Ascending SortDirection2: Variables.SortDirection.Ascending SortDirection3: Variables.SortDirection.Ascending SortedList=> TargetSubDirectories
        LOOP FOREACH TargetSubDirectory IN TargetSubDirectories
            Folder.GetFiles Folder: TargetDirectory FileFilter: $'''*.moving''' IncludeSubfolders: False FailOnAccessDenied: True SortBy1: Folder.SortBy.NoSort SortDescending1: False SortBy2: Folder.SortBy.NoSort SortDescending2: False SortBy3: Folder.SortBy.NoSort SortDescending3: False Files=> ExistingTempFiles
            IF $'''%ExistingTempFiles%%ExistingTempFiles.Count%''' > 0 THEN
                GOTO TryNextSubFolder
            END
            File.RenameChangeExtension Files: CurrentPlotFile NewExtension: $'''.moving''' IfFileExists: File.IfExists.DoNothing RenamedFiles=> RenamedFiles
            SET CurrentPlotFile TO RenamedFiles[0]
            File.Move Files: CurrentPlotFile Destination: TargetSubDirectory IfFileExists: File.IfExists.Overwrite MovedFiles=> MovedFiles
                            ON ERROR
                                GOTO TryNextSubFolder
                            END
            SET CurrentPlotFile TO MovedFiles[0]
            File.RenameChangeExtension Files: CurrentPlotFile NewExtension: $'''.plot''' IfFileExists: File.IfExists.DoNothing RenamedFiles=> RenamedFiles
            EXIT LOOP
            LABEL TryNextSubFolder
        END
    END
END
GOTO CheckForNewFiles
2 Likes

Hi,
Thanks so much for posting this, and also the Flow itself, thats really much appreciated. I have been thrashing around trying to find a nice automated way of getting plot across the network to my harvester… and this looks like it!
The problem I have is I cant seem to work out how to get the target shared network directory to have a list of mounted disks as subdirectories. Im plotting on Windows and copying across to a server running Ubuntu, with the sharing handled by Samba. I have mounted the disks on Ubuntu (disk1, disk2, disk3, disk4… etc) and they show up as Samba shares on the plotter. However, I cant figure out a way of sharing them inside a folder (so that this flow can iterate through each disk as subfolders) .
Im guessing you are running entirely on Windows maybe? Not sure if this is possible, but I feel it should be, and I feel like Im close with this!
I guess I may have to amend the flow to just point at a specific disk and fill it that way, but I was really hoping to get the disks as subfolders working, as thats so much neater.
Any ideas or clues gratefully received!

The way I do it (similar situation to yours) is that I create a list and add each drive (share) to the list. Then iterate through the list to find the drive that has room.

1 Like

Thanks WolfGT - I woke up this morning with that very thought! Hard code a list and iterate through it - its slightly less automated, but definitely an acceptable compromise.
However, Im still having problems getting the Flow to iterate the list when list items arent actually folders. I must be missing something. Dont suppose you are able to share your Flow?

The other issue I have is that copying takes so damn long. Both machines are wifi, but still, Im only getting like 5MB/sec so theres something seriously wrong there! So I created a direct ethernet connection between the windows machine and the ubuntu microserver, which should be massively quicker, if I can only get the logic on this Flow working…

thanks for any help you can offer.

Sure. Here is my flow. To help others walk through it, here is what it does.

  • Creates a list of plotters so it can determine what plotter the flow is running on. This allows the system to use a specific route/IP to copy files so no two plotters are using the same connection at a time.
  • Creates a list of destination drives.
  • Checks the temp folder for new plot files.
  • Takes the list of target drives and shuffles them.
  • If no new plot files, waits 30 seconds and looks again.
  • If it finds a new plot file, renames it to .tmp
  • There is a section of the flow that determines the size of the plot file. The value created is not currently used but left it in case I wanted it later.
  • Give each target drive a maximum file count that will fit. I do this by Farm number because the file count is determined by the drive size.
  • Pull the file count in the destination drive (you will see that I have a folder in each drive called “OG Plots”. There is also a folder called “Portable Plots” that is currently empty. These folders are there for future use. Once pooling is available, I plan on modifying the flow to fill “Portable Plots” until the drive is full and then start to remove “OG Plots” until they are gone.)
  • Once a destination is found with room. It moves the file.
  • Then it renames the plot file back to .plot.
  • Starts over
  • There are different error handling steps along the way and it logs each action to a file called CopyPlotLog.txt located on your desktop (you may want to create this file, not sure if it creates it. I don’t remember)
LABEL TheBeginning
SET SourceDirectory TO $'''E:\\'''
System.GetEnvironmentVariable Name: $'''COMPUTERNAME''' Value=> ComputerName
IF ComputerName = $'''DESKTOP-FPE121I''' THEN
    # This is Plotter 1
    SET Farm_1_IP TO $'''\\\\192.168.55.102\\'''
    SET Farm_2_IP TO $'''\\\\192.168.55.103\\'''
    SET Farm_3_IP TO $'''\\\\192.168.55.104\\'''
    SET Farm_4_IP TO $'''\\\\192.168.55.110\\'''
ELSE IF ComputerName = $'''DESKTOP-2R7Q21V''' THEN
    # This is Plotter 2
    SET Farm_1_IP TO $'''\\\\192.168.55.107\\'''
    SET Farm_2_IP TO $'''\\\\192.168.55.105\\'''
    SET Farm_3_IP TO $'''\\\\192.168.55.104\\'''
    SET Farm_4_IP TO $'''\\\\192.168.55.101\\'''
ELSE IF ComputerName = $'''DESKTOP-H79TRFH''' THEN
    # This is Plotter 3
    SET Farm_1_IP TO $'''\\\\192.168.55.108\\'''
    SET Farm_2_IP TO $'''\\\\192.168.55.106\\'''
    SET Farm_3_IP TO $'''\\\\192.168.55.104\\'''
    SET Farm_4_IP TO $'''\\\\192.168.55.111\\'''
END
Variables.CreateNewList List=> TargetDrives
Variables.AddItemToList Item: $'''%Farm_1_IP%Farm_1_D1''' List: TargetDrives NewList=> TargetDrives
Variables.AddItemToList Item: $'''%Farm_1_IP%Farm_1_D2''' List: TargetDrives NewList=> TargetDrives
Variables.AddItemToList Item: $'''%Farm_1_IP%Farm_1_D3''' List: TargetDrives NewList=> TargetDrives
Variables.AddItemToList Item: $'''%Farm_1_IP%Farm_1_D4''' List: TargetDrives NewList=> TargetDrives
Variables.AddItemToList Item: $'''%Farm_1_IP%Farm_1_D5''' List: TargetDrives NewList=> TargetDrives
Variables.AddItemToList Item: $'''%Farm_1_IP%Farm_1_D6''' List: TargetDrives NewList=> TargetDrives
Variables.AddItemToList Item: $'''%Farm_1_IP%Farm_1_D7''' List: TargetDrives NewList=> TargetDrives
Variables.AddItemToList Item: $'''%Farm_1_IP%Farm_1_D8''' List: TargetDrives NewList=> TargetDrives
Variables.AddItemToList Item: $'''%Farm_2_IP%Farm_2_D1''' List: TargetDrives NewList=> TargetDrives
Variables.AddItemToList Item: $'''%Farm_2_IP%Farm_2_D2''' List: TargetDrives NewList=> TargetDrives
Variables.AddItemToList Item: $'''%Farm_2_IP%Farm_2_D3''' List: TargetDrives NewList=> TargetDrives
Variables.AddItemToList Item: $'''%Farm_2_IP%Farm_2_D4''' List: TargetDrives NewList=> TargetDrives
Variables.AddItemToList Item: $'''%Farm_2_IP%Farm_2_D5''' List: TargetDrives NewList=> TargetDrives
Variables.AddItemToList Item: $'''%Farm_2_IP%Farm_2_D6''' List: TargetDrives NewList=> TargetDrives
Variables.AddItemToList Item: $'''%Farm_2_IP%Farm_2_D7''' List: TargetDrives NewList=> TargetDrives
Variables.AddItemToList Item: $'''%Farm_2_IP%Farm_2_D8''' List: TargetDrives NewList=> TargetDrives
Variables.AddItemToList Item: $'''%Farm_3_IP%Farm_3_D1''' List: TargetDrives NewList=> TargetDrives
Variables.AddItemToList Item: $'''%Farm_3_IP%Farm_3_D2''' List: TargetDrives NewList=> TargetDrives
Variables.AddItemToList Item: $'''%Farm_3_IP%Farm_3_D3''' List: TargetDrives NewList=> TargetDrives
Variables.AddItemToList Item: $'''%Farm_3_IP%Farm_3_D4''' List: TargetDrives NewList=> TargetDrives
Variables.AddItemToList Item: $'''%Farm_4_IP%Farm_4_D1''' List: TargetDrives NewList=> TargetDrives
Variables.AddItemToList Item: $'''%Farm_4_IP%Farm_4_D2''' List: TargetDrives NewList=> TargetDrives
Variables.AddItemToList Item: $'''%Farm_4_IP%Farm_4_D3''' List: TargetDrives NewList=> TargetDrives
Variables.AddItemToList Item: $'''%Farm_4_IP%Farm_4_D4''' List: TargetDrives NewList=> TargetDrives
Variables.AddItemToList Item: $'''%Farm_4_IP%Farm_4_D5''' List: TargetDrives NewList=> TargetDrives
Variables.AddItemToList Item: $'''%Farm_4_IP%Farm_4_D6''' List: TargetDrives NewList=> TargetDrives
Variables.AddItemToList Item: $'''%Farm_4_IP%Farm_4_D7''' List: TargetDrives NewList=> TargetDrives
Variables.AddItemToList Item: $'''%Farm_4_IP%Farm_4_D8''' List: TargetDrives NewList=> TargetDrives
Variables.AddItemToList Item: $'''%Farm_4_IP%Farm_4_D9''' List: TargetDrives NewList=> TargetDrives
Variables.AddItemToList Item: $'''%Farm_4_IP%Farm_4_D10''' List: TargetDrives NewList=> TargetDrives
Variables.AddItemToList Item: $'''%Farm_4_IP%Farm_4_D11''' List: TargetDrives NewList=> TargetDrives
Variables.AddItemToList Item: $'''%Farm_4_IP%Farm_4_D12''' List: TargetDrives NewList=> TargetDrives
Variables.AddItemToList Item: $'''%Farm_4_IP%Farm_4_D13''' List: TargetDrives NewList=> TargetDrives
Variables.AddItemToList Item: $'''%Farm_4_IP%Farm_4_D14''' List: TargetDrives NewList=> TargetDrives
Variables.AddItemToList Item: $'''%Farm_4_IP%Farm_4_D15''' List: TargetDrives NewList=> TargetDrives
Variables.AddItemToList Item: $'''%Farm_4_IP%Farm_4_D16''' List: TargetDrives NewList=> TargetDrives
Variables.AddItemToList Item: $'''%Farm_4_IP%Farm_4_D17''' List: TargetDrives NewList=> TargetDrives
Variables.AddItemToList Item: $'''%Farm_4_IP%Farm_4_D18''' List: TargetDrives NewList=> TargetDrives
Variables.AddItemToList Item: $'''%Farm_4_IP%Farm_4_D19''' List: TargetDrives NewList=> TargetDrives
Variables.AddItemToList Item: $'''%Farm_4_IP%Farm_4_D20''' List: TargetDrives NewList=> TargetDrives
LABEL CheckForNewFiles
Folder.GetFiles Folder: SourceDirectory FileFilter: $'''*.plot''' IncludeSubfolders: False FailOnAccessDenied: True SortBy1: Folder.SortBy.NoSort SortDescending1: False SortBy2: Folder.SortBy.NoSort SortDescending2: False SortBy3: Folder.SortBy.NoSort SortDescending3: False Files=> PlotFiles
Variables.ShuffleList List: TargetDrives ShuffledList=> TargetDrives
IF PlotFiles.Count = 0 THEN
    WAIT 30 
ELSE
    SET CurrentPlotFile TO PlotFiles[0]
    File.RenameChangeExtension Files: CurrentPlotFile NewExtension: $'''.tmp''' IfFileExists: File.IfExists.DoNothing RenamedFiles=> CurrentPlotFile
    # Pull the size of the plot file.
    System.RunDOSCommand DOSCommandOrApplication: $'''dir %CurrentPlotFile%''' StandardOutput=> CommandOutput2 StandardError=> CommandErrorOutput2 ExitCode=> CommandExitCode2
    Text.ParseForFirstOccurrence Text: CommandOutput2 TextToFind: $'''File(s)''' StartingPosition: 0 IgnoreCase: False OccurrencePosition=> Position
    Text.GetSubtextFrom Text: CommandOutput2 CharacterPosition: Position Subtext=> FileSize
    Text.SplitWithDelimiter Text: FileSize CustomDelimiter: $''')''' IsRegEx: False Result=> FileSize
    SET FileSize TO FileSize[1]
    Text.Trim Text: FileSize TrimOption: Text.TrimOption.Both TrimmedText=> FileSize
    Text.Reverse Text: FileSize ReversedText=> FileSize
    Text.ParseForFirstOccurrence Text: FileSize TextToFind: $'''b''' StartingPosition: 0 IgnoreCase: False OccurrencePosition=> Position3
    Text.GetSubtextFrom Text: FileSize CharacterPosition: Position3 Subtext=> FileSize
    Text.GetSubtextFrom Text: FileSize CharacterPosition: 1 Subtext=> FileSize
    Text.Trim Text: FileSize TrimOption: Text.TrimOption.Both TrimmedText=> FileSize
    Text.Reverse Text: FileSize ReversedText=> FileSize
    Text.ToNumber Text: FileSize Number=> FileSizeAsNumber
    # Now let's run through the TargetDrive list and find one that has room for this plot. Also make sure another plotter isn't currently copying to it.
    SET DriveFound TO $'''No'''
    LOOP FOREACH Drive IN TargetDrives
        IF Contains($'''%Drive%\\OG_Plots''', $'''Farm_1''', False) THEN
            SET MaxFiles TO 144
        ELSE IF Contains($'''%Drive%\\OG_Plots''', $'''Farm_2''', False) THEN
            SET MaxFiles TO 144
        ELSE IF Contains($'''%Drive%\\OG_Plots''', $'''Farm_3''', False) THEN
            SET MaxFiles TO 71
        ELSE IF Contains($'''%Drive%\\OG_Plots''', $'''Farm_4''', False) THEN
            SET MaxFiles TO 144
        END
        Folder.GetFiles Folder: $'''%Drive%\\OG_Plots''' FileFilter: $'''*.tmp''' IncludeSubfolders: False FailOnAccessDenied: True SortBy1: Folder.SortBy.NoSort SortDescending1: False SortBy2: Folder.SortBy.NoSort SortDescending2: False SortBy3: Folder.SortBy.NoSort SortDescending3: False Files=> TmpFiles
        IF TmpFiles.Count = 0 THEN
            # Let's find a TargetDirectory that has room for this new plot.
            System.RunDOSCommand DOSCommandOrApplication: $'''dir %Drive%\\OG_Plots''' StandardOutput=> CommandOutput StandardError=> CommandErrorOutput ExitCode=> CommandExitCode
            Text.Reverse Text: CommandOutput ReversedText=> CommandOutput
            Text.ParseForFirstOccurrence Text: CommandOutput TextToFind: $''')s(eliF''' StartingPosition: 0 IgnoreCase: False OccurrencePosition=> Position2
            Text.GetSubtextFrom Text: CommandOutput CharacterPosition: Position2 Subtext=> CommandOutput
                            ON ERROR
                                GOTO TheBeginning
                            END
            Text.Split Text: CommandOutput StandardDelimiter: Text.StandardDelimiter.Space DelimiterTimes: 1 Result=> CommandOutputList
            SET FileNum TO CommandOutputList[1]
            Text.Reverse Text: FileNum ReversedText=> FileNum
            Text.Trim Text: FileNum TrimOption: Text.TrimOption.Both TrimmedText=> FileNum
            Text.ToNumber Text: FileNum Number=> FileNum
                            ON ERROR
                                GOTO ResetAndStartOver
                            END
            DISABLE EXIT Code: 0
        END
        IF TmpFiles.Count > 0 THEN
            # There is an active file being copied to this folder, skip it.
            SET DriveFound TO $'''Maybe'''
            DISABLE Display.ShowMessage Title: $'''Activity Detected''' Message: $'''There is already a tmp file in this drive. Another plotter must be moving a file to it. (%Drive%)''' Icon: Display.Icon.Information Buttons: Display.Buttons.OK DefaultButton: Display.DefaultButton.Button1 IsTopMost: False ButtonPressed=> ButtonPressed
        ELSE IF FileNum >= MaxFiles THEN
            DISABLE Display.ShowMessage Title: $'''Folder Full''' Message: $'''The Plot file is too big to fit in this folder. (%Drive%)''' Icon: Display.Icon.Information Buttons: Display.Buttons.OK DefaultButton: Display.DefaultButton.Button1 IsTopMost: False ButtonPressed=> ButtonPressed
            # This destination is full (the plot file is too big to fit in the remaining free space), skip it.
        ELSE
            # This folder is currently waiting for more plots. Write to this one.
            SET DriveFound TO $'''Yes'''
            GOTO CopyTheFile
        END
    END
    LABEL CopyTheFile
    DISABLE Display.ShowMessage Title: $'''File Copying''' Message: $'''The file will fit in this folder. Proceeding with Copy. (%Drive%)''' Icon: Display.Icon.None Buttons: Display.Buttons.OK DefaultButton: Display.DefaultButton.Button1 IsTopMost: False ButtonPressed=> ButtonPressed2
    IF DriveFound = $'''Yes''' THEN
        DateTime.Local DateTimeFormat: DateTime.DateTimeFormat.DateAndTime CurrentDateTime=> CurrentDateTime
        File.WriteText File: $'''C:\\Users\\greg\\Desktop\\CopyPlotLog.txt''' TextToWrite: $'''%CurrentDateTime% - %CurrentPlotFile% Copying to %Drive%\\OG_Plots''' AppendNewLine: True IfFileExists: File.IfFileExists.Append Encoding: File.FileEncoding.DefaultEncoding
        File.Move Files: CurrentPlotFile Destination: $'''%Drive%\\OG_Plots''' IfFileExists: File.IfExists.DoNothing MovedFiles=> CurrentPlotFile
        File.RenameChangeExtension Files: CurrentPlotFile NewExtension: $'''.plot''' IfFileExists: File.IfExists.DoNothing RenamedFiles=> RenamedFiles
        DateTime.Local DateTimeFormat: DateTime.DateTimeFormat.DateAndTime CurrentDateTime=> CurrentDateTime
        File.WriteText File: $'''C:\\Users\\greg\\Desktop\\CopyPlotLog.txt''' TextToWrite: $'''%CurrentDateTime% - Plot File Moved''' AppendNewLine: True IfFileExists: File.IfFileExists.Append Encoding: File.FileEncoding.DefaultEncoding
        GOTO TheBeginning
    ELSE IF DriveFound = $'''Maybe''' THEN
        # The only folder available is currently being written to. Start over.
        File.RenameChangeExtension Files: CurrentPlotFile NewExtension: $'''.plot''' IfFileExists: File.IfExists.DoNothing RenamedFiles=> CurrentPlotFile
        DateTime.Local DateTimeFormat: DateTime.DateTimeFormat.DateAndTime CurrentDateTime=> CurrentDateTime
        File.WriteText File: $'''C:\\Users\\greg\\Desktop\\CopyPlotLog.txt''' TextToWrite: $'''%CurrentDateTime% - The only drive available is currently being written to by another plotter. (%Drive%\\OG_Plots)''' AppendNewLine: True IfFileExists: File.IfFileExists.Append Encoding: File.FileEncoding.DefaultEncoding
        WAIT 60 
        GOTO TheBeginning
    ELSE
        # No folder was found that has room for this file. Stop running this program.
        File.RenameChangeExtension Files: CurrentPlotFile NewExtension: $'''.plot''' IfFileExists: File.IfExists.DoNothing RenamedFiles=> CurrentPlotFile
        DateTime.Local DateTimeFormat: DateTime.DateTimeFormat.DateAndTime CurrentDateTime=> CurrentDateTime
        File.WriteText File: $'''C:\\Users\\greg\\Desktop\\CopyPlotLog.txt''' TextToWrite: $'''%CurrentDateTime% - All Destination Drives are full.''' AppendNewLine: True IfFileExists: File.IfFileExists.Append Encoding: File.FileEncoding.DefaultEncoding
        GOTO TheEnd
    END
END
GOTO CheckForNewFiles
LABEL ResetAndStartOver
DateTime.Local DateTimeFormat: DateTime.DateTimeFormat.DateAndTime CurrentDateTime=> CurrentDateTime
File.WriteText File: $'''C:\\Users\\greg\\Desktop\\CopyPlotLog.txt''' TextToWrite: $'''%CurrentDateTime% - Encountered an error. Resetting and starting over. (Drive: %Drive%\\OG_Plots, FileNum: %FileNum%)''' AppendNewLine: True IfFileExists: File.IfFileExists.Append Encoding: File.FileEncoding.DefaultEncoding
File.RenameChangeExtension Files: CurrentPlotFile NewExtension: $'''.plot''' IfFileExists: File.IfExists.DoNothing RenamedFiles=> CurrentPlotFile
GOTO TheBeginning
LABEL TheEnd
EXIT Code: 0

Hope this helps someone. Good luck.

2 Likes

Thanks man, really useful. I did get mine running today, though didnt manage to work out how to sort the list based on size. (ie filling up the drive with the most amount of free space first) . I see you shuffle the list - I’ll check that out. This is really useful so kudos to you for sharing.

If you look at the section that pulls the file count for a drive, you can modify that to pull the available disk space if you like. But I have found that using the file count is a lot easier. Just figure out what your drives will hold (like my 16TB drives will hold 144 plots with 80GB left over). I just have them fill the first disk it finds with room, then shuffle the list and do it again. I don’t fill them in order. Really no need for that. To be able to fill them in order of most space available, you would have to iterate through the entire list and find the one with the most room (fewest plots), then make the decision on where to write. My way just interates until it finds one with room and uses it. It works well.

2 Likes

For the Folder Sorting (line 12), the code is:
Variables.SortListByProperty List: TargetSubDirectories Property1: $'''FilesCount''' SortDirection1: Variables.SortDirection.Ascending

I think this can cause problem, when the disks don’t have same size.

I wan it to sort by its Space free, there I need something like SortListByProperty List: TargetSubDirectories Property1: $'''SpaceFree''', but “SpaceFree” is not a valid field name, and I couldn’t get any documentation of what comparative property does a folder have.

Please give me some tips…

Salut,