Add multiple actions to move files action
Moderator: Martin
Add multiple actions to move files action
In order to move files from several directories to one, a single action block is needed, but to me files to multiple directories, a separate block is needed for each. At best, this can cause a lot of extra clutter in a flow, but at worst, in can be problematic by requiring a flow to be rearranged, moving blocks around, to make room for more blocks if needs change. Adding the ability to simply add new source/destination pairs to a single action would eliminate these issues.
It would also be helpful if the text entry line, where the paths are typed, could be expanded (like the expression line when tapping the pencil icon) to make it easier to deal with long or multiple paths.
It would also be helpful if the text entry line, where the paths are typed, could be expanded (like the expression line when tapping the pencil icon) to make it easier to deal with long or multiple paths.
Re: Add multiple actions to move files action
You can prepare the source and destination folders in list and then loop upon it. Only 1 move files and single expression is needed per loop. (takes up 2 elements only) Of course still need script before that to prepare the list, but usually you have it already. You can do the same for any other elements those only use single variable at one time.
For the path field, I agree it will be useful to expand it. But typically when I have a long path already, I will usually prepare it in variable in the script before. This way, if you use your path several times, you only need to create the variable once, and refer to it in each other element. If you need to change the path, you only change once. If you look at my flow sharing, I usually declare the path to the file in the beginning of the flow. So if others want to save the file in other place, they only need to change 1 line only, rather than going thru all elements in the flow that use that path.
For the path field, I agree it will be useful to expand it. But typically when I have a long path already, I will usually prepare it in variable in the script before. This way, if you use your path several times, you only need to create the variable once, and refer to it in each other element. If you need to change the path, you only change once. If you look at my flow sharing, I usually declare the path to the file in the beginning of the flow. So if others want to save the file in other place, they only need to change 1 line only, rather than going thru all elements in the flow that use that path.
Index of Automagic useful thread List of my other useful posts (and others')
Xiaomi Redmi Note 5 (whyred), AOSP Extended v6.7 build 20200310 Official, Android Pie 9.0, Rooted.
Xiaomi Redmi Note 5 (whyred), AOSP Extended v6.7 build 20200310 Official, Android Pie 9.0, Rooted.
Re: Add multiple actions to move files action
I have to say I still think being able to add multiple source/destination pairs to a single move action would be much easier, both for building the flow and for allowing the user to browse for the directories instead of having to enter them manually into a script, but I can certainly see the merit in your method, and I also see it as a good learning opportunity. However, I've been spending a while trying to figure it out and either I'm missing something or it's not as "simple" as I imagined it would be.
This is how I imagined it:
Script block
source_list = newList("dir1","dir2",dir3",etc)
destination_list = newList("dir_a","dir_b","dir_c",etc)
Condition block
for (i in source_list) source_dir = i
for (i in destination_list) destination_dir = i
when done go to block after move block
Move block
move source_dir > destination_dir
loop back to condition block
But of course that doesn't work, unless I'm missing something. The only way I can think to do it is to determine the number of items in the lists, then use an incremented variable to count that many iterations while looping, but that would require more than two blocks. Since you said it would only take an expression and move block, I must not be seeing the solution. I considered that you might mean an expression and a script block that loops and uses the mv command, but then what would the expression be for, and would the flow wait for the move to finish? Could you elaborate on how to do this?
This is how I imagined it:
Script block
source_list = newList("dir1","dir2",dir3",etc)
destination_list = newList("dir_a","dir_b","dir_c",etc)
Condition block
for (i in source_list) source_dir = i
for (i in destination_list) destination_dir = i
when done go to block after move block
Move block
move source_dir > destination_dir
loop back to condition block
But of course that doesn't work, unless I'm missing something. The only way I can think to do it is to determine the number of items in the lists, then use an incremented variable to count that many iterations while looping, but that would require more than two blocks. Since you said it would only take an expression and move block, I must not be seeing the solution. I considered that you might mean an expression and a script block that loops and uses the mv command, but then what would the expression be for, and would the flow wait for the move to finish? Could you elaborate on how to do this?
Re: Add multiple actions to move files action
You can try the template provided by Automagic, especially the condensed version. But I create my own method.
Script
Move Files:
Source Files : {source[index]}
Target : {destination[index]}
Expression
True, go back to Move Files
False, continue your flow (loop finished), example Notification on Screen : Finsihed Moving the file!
- The source and destination list must be the same length.
- Index is initiated to 0 before the loop
- The loop part only Move Files and Expression
- In expression, the index is +1, then checked if is less than the length, looped back to Move Files.
- If already equal to the length (index already reached end of the list), then finished the loop, continue to next element.
- This can be modified to any other action/condition you want to loop on.
- This is just one of the loop style, you can also use map, nested list, expression first or execution count for some cases.
For multiple source/destination, how many is enough? 3, 5, 10? That would make the action become too long and inefficient for most users. Any aditional field in the action will add additional footprint on the xml file configuration. So better use the loop method, it can be implemented right now and can be replicated on any element you want to loop.
Script
Code: Select all
source = newList("dir1","dir2",dir3");
destination = newList("dir_a","dir_b","dir_c");
index = 0;
Source Files : {source[index]}
Target : {destination[index]}
Expression
Code: Select all
(index = index + 1) < length(source)
False, continue your flow (loop finished), example Notification on Screen : Finsihed Moving the file!
- The source and destination list must be the same length.
- Index is initiated to 0 before the loop
- The loop part only Move Files and Expression
- In expression, the index is +1, then checked if is less than the length, looped back to Move Files.
- If already equal to the length (index already reached end of the list), then finished the loop, continue to next element.
- This can be modified to any other action/condition you want to loop on.
- This is just one of the loop style, you can also use map, nested list, expression first or execution count for some cases.
For multiple source/destination, how many is enough? 3, 5, 10? That would make the action become too long and inefficient for most users. Any aditional field in the action will add additional footprint on the xml file configuration. So better use the loop method, it can be implemented right now and can be replicated on any element you want to loop.
Index of Automagic useful thread List of my other useful posts (and others')
Xiaomi Redmi Note 5 (whyred), AOSP Extended v6.7 build 20200310 Official, Android Pie 9.0, Rooted.
Xiaomi Redmi Note 5 (whyred), AOSP Extended v6.7 build 20200310 Official, Android Pie 9.0, Rooted.
Re: Add multiple actions to move files action
I keep forgetting about the index in []. I had actually thought to try doing it with that, but I guess in the process of it all it slipped my mind. That makes sense, and I should be able to get it working now. I also didn't realize there was a length() function. I had created a couple for loops to increment a variable for each item in each list, then compared the variables to make sure they're the same, so that function will obviously be much better. That is one reason why being able to simply add more items to the move block would be better, because it's much easier to keep track of
than
which is why the check to make sure they each have the same number of items is even necessary, and that still doesn't deal with the issue of making sure the nth item in the source list corresponds to the nth item in the destination list, i.e. that there wasn't a mistake of swapping something accidentally, or if you have 20+ items and need to change one of the middle ones. Just becomes a lot more challenging to deal with.
As for the length of the action, I'm not suggesting it should have a certain number of source and destination pairs, e.g. 10 or 20. I'm saying it should have one, like it does, with the ability to add more. So if one more is needed, the user presses an add button (plus icon) once, if they need another, they press it again, and so on. This may clutter the xml more, I don't know, but personally I don't think that matters much. Granted, a loop may be better as far as efficiency and a smaller xml (though I would think the extra blocks and code would actually make the xml larger), and certainly it's better for teaching programming vs just having an "easy mode" built-in, but the app should be as easy as reasonably possible for all users, and the fact that it is for the most part is why I decided on it vs the alternatives. So I think allowing the user to add new source/destination pairs as needed in a single move block would do a lot in that respect.
Code: Select all
Source dir1
Destination dir1
Source dir2,Source dir3,Source dir4,Source dir5,Source dir6
Destination dir2
Source dir7,Source dir8
Destination dir3
Code: Select all
Source dir1,Source dir2,Source dir3,Source dir4,Source dir5,Source dir6,Source dir7,Source dir8
Destination dir1,Destination dir2,Destination dir2,Destination dir2,Destination dir2,Destination dir2,Destination dir3,Destination dir3
As for the length of the action, I'm not suggesting it should have a certain number of source and destination pairs, e.g. 10 or 20. I'm saying it should have one, like it does, with the ability to add more. So if one more is needed, the user presses an add button (plus icon) once, if they need another, they press it again, and so on. This may clutter the xml more, I don't know, but personally I don't think that matters much. Granted, a loop may be better as far as efficiency and a smaller xml (though I would think the extra blocks and code would actually make the xml larger), and certainly it's better for teaching programming vs just having an "easy mode" built-in, but the app should be as easy as reasonably possible for all users, and the fact that it is for the most part is why I decided on it vs the alternatives. So I think allowing the user to add new source/destination pairs as needed in a single move block would do a lot in that respect.
Re: Add multiple actions to move files action
You can use the map style to map each source to its destination.
Source files : {source[index]}
Target : {src_dst[source[index]]}
If I want to use map style, I prefer this method. As each source is mapped to exactly one destination, although the destination can be duplicated. But if you prefer to keep the destination as the key, you can reverse the source and destination and use list to hold multiple sources.
Source files : {dst_src[destination[index]],listformat,comma}
Target : {destination[index]}
I understand that not everyone are going into map/list method. But by learning how to use it, we unlocked the power of the looping and can use it on any element. If not, we are going to request multiple source/destination not only for move files, but for copy files, and maybe other elements as well.
And the other problem is to guess how many is enough. If Martin put 3 pairs, then someone might say not enough. Added to be 10, then another will keep adding up requesting 20, 30, and so on. Even if we can add one at a time, AFAIK, the program still have to reserve the maximum limit. So even if we use 2 only, and limit is 10, the reserved memory is still 10. It will takes up more space and runtime memory, as each field will have to reserve some extra memory for it. It will slowdown everyone's flows, as Automagic become memory hogging, not the scenario I want. CMIIW. Imagine this happen also for other elements.
So if Martin decide to add the feature, I would suggest to split it to separate action, as "Move Files (multiple src-dst)". This way, it doesn't affect others' flow, as it is a separate action. Everyone can use their preferred style. For the number of the fields, maybe 10 pairs is enough for most. If someone need 30, they just add 3 actions, instead of 30 "Move Files".
I don't know what Martin's thought on this. But I think if we have ways to do it using loop, it is better to use loop.
In mean time, while we don't know if this feature will be implemented or not (or when), available workaround :
1. Create as many "Move Files" as needed. For less than 5 pairs, this should be good enough for most cases.
2. Create another flow which contains as many "Move Files" as we want and use Execute flows from the main flow. We only need 1 action in the main flow
3. Use one of the looping method above (either list or map style). We need 1 action and 1 expression to do the loop.
Code: Select all
src_dst = newMapFromValues(
"src1", "dst1",
"src2", "dst2",
"src3", "dst2",
"src4", "dst3",
"src5", "dst3") ;
source = getMapKeys(src_dst);
index = 0;
Target : {src_dst[source[index]]}
If I want to use map style, I prefer this method. As each source is mapped to exactly one destination, although the destination can be duplicated. But if you prefer to keep the destination as the key, you can reverse the source and destination and use list to hold multiple sources.
Code: Select all
dst_src = newMapFromValues(
"dst1", newList("src1"),
"dst2", newList("src2", "src3"),
"dst3", newList("src4", "src4"));
destination = getMapKeys(dst_src);
index = 0;
Target : {destination[index]}
I understand that not everyone are going into map/list method. But by learning how to use it, we unlocked the power of the looping and can use it on any element. If not, we are going to request multiple source/destination not only for move files, but for copy files, and maybe other elements as well.
And the other problem is to guess how many is enough. If Martin put 3 pairs, then someone might say not enough. Added to be 10, then another will keep adding up requesting 20, 30, and so on. Even if we can add one at a time, AFAIK, the program still have to reserve the maximum limit. So even if we use 2 only, and limit is 10, the reserved memory is still 10. It will takes up more space and runtime memory, as each field will have to reserve some extra memory for it. It will slowdown everyone's flows, as Automagic become memory hogging, not the scenario I want. CMIIW. Imagine this happen also for other elements.
So if Martin decide to add the feature, I would suggest to split it to separate action, as "Move Files (multiple src-dst)". This way, it doesn't affect others' flow, as it is a separate action. Everyone can use their preferred style. For the number of the fields, maybe 10 pairs is enough for most. If someone need 30, they just add 3 actions, instead of 30 "Move Files".
I don't know what Martin's thought on this. But I think if we have ways to do it using loop, it is better to use loop.
In mean time, while we don't know if this feature will be implemented or not (or when), available workaround :
1. Create as many "Move Files" as needed. For less than 5 pairs, this should be good enough for most cases.
2. Create another flow which contains as many "Move Files" as we want and use Execute flows from the main flow. We only need 1 action in the main flow
3. Use one of the looping method above (either list or map style). We need 1 action and 1 expression to do the loop.
Index of Automagic useful thread List of my other useful posts (and others')
Xiaomi Redmi Note 5 (whyred), AOSP Extended v6.7 build 20200310 Official, Android Pie 9.0, Rooted.
Xiaomi Redmi Note 5 (whyred), AOSP Extended v6.7 build 20200310 Official, Android Pie 9.0, Rooted.
Re: Add multiple actions to move files action
Darn. I just finished making all the changes to the flow, including making the loop, and now I may need to change it to use mapping. I'll have to think about it and decide which way is better for this use. Either way, it's finally almost done, just needs some testing and then it should be ready for release, so hopefully others can use it. It's funny how things like this always grow so much larger and more complex than they start. I love coming up with new ideas to improve on projects and figuring out how to implement them.
As for the loop, I hadn't realized you could actually perform a scripting action (incrementing a variable) in a condition. I'd always thought you could only perform a check. So that's a big part of why I couldn't figure out how to do it. Even after reading your explanation (and waiting several hours to try and figure it out from memory instead of simply following your instructions, to better learn), I found myself wondering again just how to accomplish it without another script block, then took another look at your prior post. It took a closer, second look to see what you were doing there. Very interesting technique.
I didn't realize the overhead for simply having the option to add extra paths to the action; I just figured they were handled as needed. In that case, I can definitely see the case for not adding the feature, and adding separate ones for handling multiple paths seems like it wouldn't be worth it, so I agree we'll have to let Martin make the call (which of course he would anyway) as to what would work best.
The idea of simply calling another flow that has the actions in it occurred to me, both for this and for other things, but I hate to clutter the flow list and prefer to keep things contained. What would really be nice as an alternative to that, and something I've wished for at least a couple times so far, is a subroutine feature, where a trigger-like box can be added off to the side, with its own mini-flow, and called from the main part of the flow, returning to where it was called from once done. Such a feature would be very helpful in certain circumstances. And I realize this can be done by adding triggers and trigger conditions to the flow, but that's not nearly as clean and doesn't always work.
As for the loop, I hadn't realized you could actually perform a scripting action (incrementing a variable) in a condition. I'd always thought you could only perform a check. So that's a big part of why I couldn't figure out how to do it. Even after reading your explanation (and waiting several hours to try and figure it out from memory instead of simply following your instructions, to better learn), I found myself wondering again just how to accomplish it without another script block, then took another look at your prior post. It took a closer, second look to see what you were doing there. Very interesting technique.
I didn't realize the overhead for simply having the option to add extra paths to the action; I just figured they were handled as needed. In that case, I can definitely see the case for not adding the feature, and adding separate ones for handling multiple paths seems like it wouldn't be worth it, so I agree we'll have to let Martin make the call (which of course he would anyway) as to what would work best.
The idea of simply calling another flow that has the actions in it occurred to me, both for this and for other things, but I hate to clutter the flow list and prefer to keep things contained. What would really be nice as an alternative to that, and something I've wished for at least a couple times so far, is a subroutine feature, where a trigger-like box can be added off to the side, with its own mini-flow, and called from the main part of the flow, returning to where it was called from once done. Such a feature would be very helpful in certain circumstances. And I realize this can be done by adding triggers and trigger conditions to the flow, but that's not nearly as clean and doesn't always work.
Re: Add multiple actions to move files action
Hahaha, don't be afraid of changing the code even after you successfully using one of the method. I sometimes redo the whole script just to test different idea and see which one works better and expandable. Just like I tear up the secure setting logger from the map style back to list style, changing more than half ot the flow's backbone. Turns out, I prefer list after several trial.
Expression can be used just like script. As long as the last executed line give result in true or false. Or you can also use return true/false in the middle of the expression and it will stop the script there immediately; making expression very useful for branching.
The one line expression for the loop used to be several lines. It originally comes from
Then I know I can save variable space declaration by using the length directly. This will save some runtime memory, even though a bit only.
Then later find out that the left operand in the comparison can be put into a block, saving another line of execution.
This is how my scripting style changed over time. And i usually get it by several try and error, changing the code over time.
But at most times, I prefer readability. So I don't just stuff the whole tens lines of script into single one. The expression above considered still readable enough (maybe because I already used to it).
Reserving space for variable/field is common in programming. If you share a flow, and fill some actions, while leaving most field blanks; you can still see that at the xml level, those blank fields still consume empty xml tag space. That's why adding multiple fields still consume space even though they aren't being used. On the other side, using loop might consume bigger space for low loop count (as we need to write extra script). But once you past 10, 100, 1000, the loop started to save much more space than the extra line of script we use. Not to mention that using loop, we can have practically unlimited loop (compared to limited reserved field in the action), only limited by the hardware we have (well, technically we have limit of 10000 loop, but we still can loop that 10000 again and again).
As for the mini flow, there has been discussion before. I prefer to have subfolder flow within group : viewtopic.php?f=4&t=7687
So everything still works as currently, the only addition is how we arrange the flow list in Automagic.
Expression can be used just like script. As long as the last executed line give result in true or false. Or you can also use return true/false in the middle of the expression and it will stop the script there immediately; making expression very useful for branching.
The one line expression for the loop used to be several lines. It originally comes from
Code: Select all
len = length(source);
index = index + 1;
index < len;
Code: Select all
index = index + 1;
index < length(source);
Code: Select all
(index = index + 1) < length(source)
But at most times, I prefer readability. So I don't just stuff the whole tens lines of script into single one. The expression above considered still readable enough (maybe because I already used to it).
Reserving space for variable/field is common in programming. If you share a flow, and fill some actions, while leaving most field blanks; you can still see that at the xml level, those blank fields still consume empty xml tag space. That's why adding multiple fields still consume space even though they aren't being used. On the other side, using loop might consume bigger space for low loop count (as we need to write extra script). But once you past 10, 100, 1000, the loop started to save much more space than the extra line of script we use. Not to mention that using loop, we can have practically unlimited loop (compared to limited reserved field in the action), only limited by the hardware we have (well, technically we have limit of 10000 loop, but we still can loop that 10000 again and again).
As for the mini flow, there has been discussion before. I prefer to have subfolder flow within group : viewtopic.php?f=4&t=7687
So everything still works as currently, the only addition is how we arrange the flow list in Automagic.
Index of Automagic useful thread List of my other useful posts (and others')
Xiaomi Redmi Note 5 (whyred), AOSP Extended v6.7 build 20200310 Official, Android Pie 9.0, Rooted.
Xiaomi Redmi Note 5 (whyred), AOSP Extended v6.7 build 20200310 Official, Android Pie 9.0, Rooted.
Re: Add multiple actions to move files action
So I can define a variable with an "if var not defined set var" statement inside an expression before saying var == whatever, instead of using a separate script block in front of it. Nice.
Using return true/false sounds intriguing, I'll have to look into possible uses.
I could be completely wrong, but i thought the XML is only used for export/import, and the internal code of a flow is stored another way, likely more efficient and lacking thise unused details. In that case, it wouldn't make the flow any bigger or less efficient, it would only make the XML a bit more bloated when sharing or backing up the flow, which isn't really a big deal.
Using return true/false sounds intriguing, I'll have to look into possible uses.
I could be completely wrong, but i thought the XML is only used for export/import, and the internal code of a flow is stored another way, likely more efficient and lacking thise unused details. In that case, it wouldn't make the flow any bigger or less efficient, it would only make the XML a bit more bloated when sharing or backing up the flow, which isn't really a big deal.
Re: Add multiple actions to move files action
Apparently the return true/false in a condition can't be used the way I imagined, so it seems to be of much more limited use than I originally thought. I wanted to make a conditional block as follows:
if (trigger == "Manual)
{
return true
}
if (startsWith(trigger,"App Task Started"))
{
return false
}
in order to have it execute one branch if the flow is triggered manually, the other if executed by launching the specified apps, or simply stop if neither condition applies. Unfortunately, it seems it must result in either true or false, meaning I can't have it act as a three-way "split" (really two-way and a dead-end). Is there a way to do this? I thought maybe there was a stop/end/exit command I could use at the end, but don't seen anything.
I'm also still struggling to figure out how to get the mapping to work. The files transfer as expected when using lists, but when using the maps it doesn't work right. I created a test file in each directory, and each one is renamed to "_" in the target directory. It also creates a directory with that name ( "_" ) in each of the target directories each time.
Also, when iterating through the list, when index is incremented, wouldn't it go from 0 being src1 to 1 being dst1 and back and forth between source and target paths? It seems like it should be incremented by two each time, to go from 0 to 2 to 4 and so on. Unfortunately, I don't really understand what's going on with the mapping, which is probably why I can't get it to work. I like to understand something when I use it, but I don't know the first thing about mapping.
if (trigger == "Manual)
{
return true
}
if (startsWith(trigger,"App Task Started"))
{
return false
}
in order to have it execute one branch if the flow is triggered manually, the other if executed by launching the specified apps, or simply stop if neither condition applies. Unfortunately, it seems it must result in either true or false, meaning I can't have it act as a three-way "split" (really two-way and a dead-end). Is there a way to do this? I thought maybe there was a stop/end/exit command I could use at the end, but don't seen anything.
I'm also still struggling to figure out how to get the mapping to work. The files transfer as expected when using lists, but when using the maps it doesn't work right. I created a test file in each directory, and each one is renamed to "_" in the target directory. It also creates a directory with that name ( "_" ) in each of the target directories each time.
Also, when iterating through the list, when index is incremented, wouldn't it go from 0 being src1 to 1 being dst1 and back and forth between source and target paths? It seems like it should be incremented by two each time, to go from 0 to 2 to 4 and so on. Unfortunately, I don't really understand what's going on with the mapping, which is probably why I can't get it to work. I like to understand something when I use it, but I don't know the first thing about mapping.