How do I make my macro display the percentage of files copied?

I created a macro to copy files or folders from my computer to my USB drive. Is there any way to display the amount of data copied as a percentage of the total amount of the data to be copied and update it continuously until 100% of the data is copied?

Since you iterate through the files yourself, you could count the lines in the FilesToCopy variable and then keep track of the index and display the result as a percentage.

  • Set Variable Count to FilesToCopy
  • Filter Variable Count by Count Lines.
  • Set Variable Index to 0
  • For Each individualPath in FilesToCopy
    • Set Variable Percent to Calculation Index/Count Format 0.0
    • Notify %Percent%%% Completed
    • Set Variable Index to Index + 1
    • Etc

If you don't mind using AppleScript, you can display a traditional progress bar using ASObjC.
See the following for an example:

... and in Yosemite,

if your Applescript

  1. sets an integer value for progress total steps,
  2. updates the strings for progress description and progress additional description on each loop of the process, and
  3. also updates the integer for progress completed steps on each loop
set {dlm, my text item delimiters} to {my text item delimiters, " "}
set lst to text items of "alpha beta gamma delta epsilon zeta eta theta"
set my text item delimiters to dlm

set lng to length of lst

set progress total steps to lng
repeat with i from 1 to lng
	set str to item i of lst
	set progress description to (i & " of " & lng)
	set progress additional description to str
	say str
	set progress completed steps to i
end repeat

You can then:

  • choose Save As Application (rather than Script or Text) in Script Editor,
  • use a an Activate a specific application action in Keyboard Maestro (rather than an execute script action) (choose Other in the Application selection dialog, and browse to the location of your saved .app file,
  • and watch a simple progress bar when the action runs …

( haven't really used this much myself, but I notice that it seems to work ... )

1 Like

PS a JavaScript for Applications version might look something like:

  var	a = Application.currentApplication();
  	a.includeStandardAdditions = true;

  var	lst = "alpha beta gamma delta epsilon zeta eta theta".split(" "),
  	wds = lst.length,
  	i = 0;

  Progress.totalUnitCount = wds;

  lst.forEach(function (w) {
 
  	Progress.description = (i+1) + " of " + wds;
  	Progress.additionalDescription = w;
  	Progress.completedUnitCount = i++;
	
	a.say(w);
  });
1 Like

Very Nice! And very simple. I like it!
Too bad I'm not running Yosemite yet. :frowning:

All things come to those who wait … much to be said for upgrading late, and waiting for things to get ironed out.

( I upgraded early this time for JXA Javascript, and in fact it’s been fine ( and I prefer it visually ) but I have to admit that I usually try to trail one version behind )

Thanks for the options you have given me.

Sorry, but I can not get my head around how to implement this in a macro.
Should all the copying/moving be don in AppleScript? Or can I use KMs built in copy/moving actions?

If it is not to much trouble, then an example macro or screenshot would be nice.
Thanks.

The process needs to be segmented and each segment processed in the inner execute+report loop, so the default would certainly be to do the processing from inside the script …

I’ll see if I can sketch something tonight

Should all the copying/moving be done in AppleScript?
Or can I use KMs built in copy/moving actions?

Progress bar updates are made inside a scripting loop, so the vanilla route is for that loop to contain two parts:

  • Do something to the next batch of lines ( file paths for example )
  • Update the progress bar

In Javascript, for example, it might look a bit like this:

// INNER LOOP: EXECUTE AND REPORT IN BATCHES
for (var i = 0; i < lngReports; i++) {
	// GET THE NEXT SET OF LINES
	lngStart = i * lngBatch;
	lngEnd = lngStart + lngBatch;
	lstBatch = lstLines.slice(lngStart, lngEnd);

	strBatch = lstBatch.join('\n');

	if (strBatch) {

		// 1. DO SOMETHING WITH THIS BATCH OF LINES
		copyFilesByPathName(strBatch, strTarget);

		// 2. AND REPORT ON NUMBER OF LINES DEALT WITH SO FAR
		Progress.description = (lngEnd + " of " + lngLines);
		Progress.additionalDescription = lstLines[lngEnd];
		Progress.completedUnitCount = lngEnd;
		
	}
}

Of course, we can call a macro from inside a script loop, so I did experiment with sketching a plugin which:

  • Takes the name of a macro,
  • the name of the variable which that macro reads and works on,
  • and the number (N) of progress bar updates that we want (more is fun, but slows the process)

and then feeds lines in N batches from another variable or clipboard to the one which the macro reads, updating the progress bar after each mouthful that has been fed to the client macro.

For example, if you began by creating or installing a very simple test macro which reads a variable called set of lines,

Read some lines aloud.kmmacros (1.2 KB)

You could then either use it on its own (without a progress bar),
or call it from the experimental plugin at: Displaying a progress bar as a macro works through a collection of lines

It's just an experiment – I'm not sure which approach is really simpler: doing the work inside the script, or using the plugin : - )

Thanks.

I will try to look to implement this in some macros.