This is an automated email from the ASF dual-hosted git repository.

mcasters pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/hop.git


The following commit(s) were added to refs/heads/main by this push:
     new 05e722da59 Issue #1979 (Move Files action code cleanup and IT) (#6934)
05e722da59 is described below

commit 05e722da59a04e806e11623c370f8fc5921ad9a5
Author: Matt Casters <[email protected]>
AuthorDate: Thu Apr 2 15:18:53 2026 +0200

    Issue #1979 (Move Files action code cleanup and IT) (#6934)
---
 integration-tests/actions/files-0015/files.zip     | Bin 0 -> 782 bytes
 integration-tests/actions/main-0015-move-files.hwf | 370 ++++++++++++
 .../actions/movefiles/ActionMoveFiles.java         | 671 +++++++--------------
 .../actions/movefiles/ActionMoveFilesDialog.java   | 133 ++--
 .../actions/movefiles/ActionMoveFilesTest.java     |  75 +++
 .../actions/movefiles/AzureMoveFilesIT.java        |  67 +-
 .../actions/movefiles/MoveFilesActionHelper.java   |   1 -
 .../WorkflowActionMoveFilesLocalTest.java          |  82 ++-
 .../movefiles/WorkflowActionMoveFilesTest.java     |  94 ---
 .../src/test/resources/action-move-files.xml       |  55 ++
 10 files changed, 854 insertions(+), 694 deletions(-)

diff --git a/integration-tests/actions/files-0015/files.zip 
b/integration-tests/actions/files-0015/files.zip
new file mode 100644
index 0000000000..e8c0b432fc
Binary files /dev/null and b/integration-tests/actions/files-0015/files.zip 
differ
diff --git a/integration-tests/actions/main-0015-move-files.hwf 
b/integration-tests/actions/main-0015-move-files.hwf
new file mode 100644
index 0000000000..3fbdf2a034
--- /dev/null
+++ b/integration-tests/actions/main-0015-move-files.hwf
@@ -0,0 +1,370 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+-->
+<workflow>
+  <name>main-0015-move-files</name>
+  <name_sync_with_filename>Y</name_sync_with_filename>
+  <description/>
+  <extended_description/>
+  <workflow_version/>
+  <created_user>-</created_user>
+  <created_date>2026/04/02 13:34:56.591</created_date>
+  <modified_user>-</modified_user>
+  <modified_date>2026/04/02 13:34:56.591</modified_date>
+  <parameters>
+    </parameters>
+  <actions>
+    <action>
+      <name>Start</name>
+      <description/>
+      <type>SPECIAL</type>
+      <attributes/>
+      <repeat>N</repeat>
+      <schedulerType>0</schedulerType>
+      <intervalSeconds>0</intervalSeconds>
+      <intervalMinutes>60</intervalMinutes>
+      <DayOfMonth>1</DayOfMonth>
+      <weekDay>1</weekDay>
+      <minutes>0</minutes>
+      <hour>12</hour>
+      <doNotWaitOnFirstExecution>N</doNotWaitOnFirstExecution>
+      <parallel>N</parallel>
+      <xloc>50</xloc>
+      <yloc>50</yloc>
+      <attributes_hac/>
+    </action>
+    <action>
+      <name>move to processing</name>
+      <description/>
+      <type>MOVE_FILES</type>
+      <attributes/>
+      <move_empty_folders>N</move_empty_folders>
+      <arg_from_previous>N</arg_from_previous>
+      <include_subfolders>N</include_subfolders>
+      <add_result_filesname>N</add_result_filesname>
+      <destination_is_a_file>N</destination_is_a_file>
+      <create_destination_folder>N</create_destination_folder>
+      <add_date>N</add_date>
+      <add_time>N</add_time>
+      <SpecifyFormat>N</SpecifyFormat>
+      <date_time_format/>
+      <nr_errors_less_than>10</nr_errors_less_than>
+      <success_condition>success_if_no_errors</success_condition>
+      <AddDateBeforeExtension>N</AddDateBeforeExtension>
+      <DoNotKeepFolderStructure>N</DoNotKeepFolderStructure>
+      <iffileexists>overwrite_file</iffileexists>
+      <destinationFolder/>
+      <ifmovedfileexists>do_nothing</ifmovedfileexists>
+      <moved_date_time_format/>
+      <create_move_to_folder>N</create_move_to_folder>
+      <add_moved_date>N</add_moved_date>
+      <add_moved_time>N</add_moved_time>
+      <SpecifyMoveFormat>N</SpecifyMoveFormat>
+      <AddMovedDateBeforeExtension>N</AddMovedDateBeforeExtension>
+      <simulate>N</simulate>
+      <fields>
+        <field>
+          <source_filefolder>${java.io.tmpdir}/action-0015/</source_filefolder>
+          
<destination_filefolder>${java.io.tmpdir}/action-0015/processing/</destination_filefolder>
+          <wildcard>.*\.txt</wildcard>
+        </field>
+      </fields>
+      <parallel>N</parallel>
+      <xloc>208</xloc>
+      <yloc>144</yloc>
+      <attributes_hac/>
+    </action>
+    <action>
+      <name>Unzip files-0015/files.zip</name>
+      <description/>
+      <type>UNZIP</type>
+      <attributes/>
+      <zipfilename>${PROJECT_HOME}/files-0015/</zipfilename>
+      <afterunzip>0</afterunzip>
+      <wildcard>.*\.txt</wildcard>
+      <wildcardexclude/>
+      <targetdirectory>${java.io.tmpdir}/action-0015</targetdirectory>
+      <movetodirectory/>
+      <addfiletoresult>N</addfiletoresult>
+      <isfromprevious>N</isfromprevious>
+      <adddate>N</adddate>
+      <addtime>N</addtime>
+      <SpecifyFormat>N</SpecifyFormat>
+      <date_time_format/>
+      <rootzip>N</rootzip>
+      <createfolder>Y</createfolder>
+      <nr_limit>5</nr_limit>
+      <wildcardSource>.*files.zip</wildcardSource>
+      <iffileexists>1</iffileexists>
+      <create_move_to_directory>N</create_move_to_directory>
+      <addOriginalTimestamp>N</addOriginalTimestamp>
+      <setOriginalModificationDate>N</setOriginalModificationDate>
+      <success_condition>success_if_no_errors</success_condition>
+      <parallel>N</parallel>
+      <xloc>208</xloc>
+      <yloc>48</yloc>
+      <attributes_hac/>
+    </action>
+    <action>
+      <name>/tmp/action-0015/processing</name>
+      <description/>
+      <type>CREATE_FOLDER</type>
+      <attributes/>
+      <foldername>${java.io.tmpdir}/action-0015/processing</foldername>
+      <fail_of_folder_exists>N</fail_of_folder_exists>
+      <parallel>N</parallel>
+      <xloc>640</xloc>
+      <yloc>48</yloc>
+      <attributes_hac/>
+    </action>
+    <action>
+      <name>/tmp/action-0015/archive</name>
+      <description/>
+      <type>CREATE_FOLDER</type>
+      <attributes/>
+      <foldername>${java.io.tmpdir}/action-0015/archive</foldername>
+      <fail_of_folder_exists>N</fail_of_folder_exists>
+      <parallel>N</parallel>
+      <xloc>864</xloc>
+      <yloc>48</yloc>
+      <attributes_hac/>
+    </action>
+    <action>
+      <name>move to archive</name>
+      <description/>
+      <type>MOVE_FILES</type>
+      <attributes/>
+      <move_empty_folders>N</move_empty_folders>
+      <arg_from_previous>N</arg_from_previous>
+      <include_subfolders>N</include_subfolders>
+      <add_result_filesname>N</add_result_filesname>
+      <destination_is_a_file>N</destination_is_a_file>
+      <create_destination_folder>N</create_destination_folder>
+      <add_date>N</add_date>
+      <add_time>N</add_time>
+      <SpecifyFormat>N</SpecifyFormat>
+      <date_time_format/>
+      <nr_errors_less_than>10</nr_errors_less_than>
+      <success_condition>success_if_no_errors</success_condition>
+      <AddDateBeforeExtension>N</AddDateBeforeExtension>
+      <DoNotKeepFolderStructure>N</DoNotKeepFolderStructure>
+      <iffileexists>overwrite_file</iffileexists>
+      <destinationFolder/>
+      <ifmovedfileexists>do_nothing</ifmovedfileexists>
+      <moved_date_time_format/>
+      <create_move_to_folder>N</create_move_to_folder>
+      <add_moved_date>N</add_moved_date>
+      <add_moved_time>N</add_moved_time>
+      <SpecifyMoveFormat>N</SpecifyMoveFormat>
+      <AddMovedDateBeforeExtension>N</AddMovedDateBeforeExtension>
+      <simulate>N</simulate>
+      <fields>
+        <field>
+          
<source_filefolder>${java.io.tmpdir}/action-0015/processing/</source_filefolder>
+          
<destination_filefolder>${java.io.tmpdir}/action-0015/archive/</destination_filefolder>
+          <wildcard>.*\.txt</wildcard>
+        </field>
+      </fields>
+      <parallel>N</parallel>
+      <xloc>208</xloc>
+      <yloc>240</yloc>
+      <attributes_hac/>
+    </action>
+    <action>
+      <name>empty source folder</name>
+      <description/>
+      <type>EVAL_FILES_METRICS</type>
+      <attributes/>
+      <scale>bytes</scale>
+      <source_files>files</source_files>
+      <evaluation_type>count</evaluation_type>
+      <comparevalue>0</comparevalue>
+      <successnumbercondition>equal</successnumbercondition>
+      <fields>
+        <field>
+          <source_filefolder>${java.io.tmpdir}/action-0015/</source_filefolder>
+          <wildcard>.*\.txt</wildcard>
+        </field>
+      </fields>
+      <parallel>N</parallel>
+      <xloc>416</xloc>
+      <yloc>144</yloc>
+      <attributes_hac/>
+    </action>
+    <action>
+      <name>5 files in processing</name>
+      <description/>
+      <type>EVAL_FILES_METRICS</type>
+      <attributes/>
+      <scale>bytes</scale>
+      <source_files>files</source_files>
+      <evaluation_type>count</evaluation_type>
+      <comparevalue>5</comparevalue>
+      <successnumbercondition>equal</successnumbercondition>
+      <fields>
+        <field>
+          
<source_filefolder>${java.io.tmpdir}/action-0015/processing/</source_filefolder>
+          <wildcard>.*\.txt</wildcard>
+        </field>
+      </fields>
+      <parallel>N</parallel>
+      <xloc>640</xloc>
+      <yloc>144</yloc>
+      <attributes_hac/>
+    </action>
+    <action>
+      <name>empty processing folder</name>
+      <description/>
+      <type>EVAL_FILES_METRICS</type>
+      <attributes/>
+      <scale>bytes</scale>
+      <source_files>files</source_files>
+      <evaluation_type>count</evaluation_type>
+      <comparevalue>0</comparevalue>
+      <successnumbercondition>equal</successnumbercondition>
+      <fields>
+        <field>
+          
<source_filefolder>${java.io.tmpdir}/action-0015/processing/</source_filefolder>
+          <wildcard>.*\.txt</wildcard>
+        </field>
+      </fields>
+      <parallel>N</parallel>
+      <xloc>416</xloc>
+      <yloc>240</yloc>
+      <attributes_hac/>
+    </action>
+    <action>
+      <name>5 files in archive</name>
+      <description/>
+      <type>EVAL_FILES_METRICS</type>
+      <attributes/>
+      <scale>bytes</scale>
+      <source_files>files</source_files>
+      <evaluation_type>count</evaluation_type>
+      <comparevalue>5</comparevalue>
+      <successnumbercondition>equal</successnumbercondition>
+      <fields>
+        <field>
+          
<source_filefolder>${java.io.tmpdir}/action-0015/archive/</source_filefolder>
+          <wildcard>.*\.txt</wildcard>
+        </field>
+      </fields>
+      <parallel>N</parallel>
+      <xloc>640</xloc>
+      <yloc>240</yloc>
+      <attributes_hac/>
+    </action>
+    <action>
+      <name>5 files in /tmp/action-0015/</name>
+      <description/>
+      <type>EVAL_FILES_METRICS</type>
+      <attributes/>
+      <scale>bytes</scale>
+      <source_files>files</source_files>
+      <evaluation_type>count</evaluation_type>
+      <comparevalue>5</comparevalue>
+      <successnumbercondition>equal</successnumbercondition>
+      <fields>
+        <field>
+          <source_filefolder>${java.io.tmpdir}/action-0015/</source_filefolder>
+          <wildcard>.*\.txt</wildcard>
+        </field>
+      </fields>
+      <parallel>N</parallel>
+      <xloc>416</xloc>
+      <yloc>48</yloc>
+      <attributes_hac/>
+    </action>
+  </actions>
+  <hops>
+    <hop>
+      <from>Start</from>
+      <to>Unzip files-0015/files.zip</to>
+      <enabled>Y</enabled>
+      <evaluation>Y</evaluation>
+      <unconditional>Y</unconditional>
+    </hop>
+    <hop>
+      <from>/tmp/action-0015/processing</from>
+      <to>/tmp/action-0015/archive</to>
+      <enabled>Y</enabled>
+      <evaluation>Y</evaluation>
+      <unconditional>N</unconditional>
+    </hop>
+    <hop>
+      <from>/tmp/action-0015/archive</from>
+      <to>move to processing</to>
+      <enabled>Y</enabled>
+      <evaluation>Y</evaluation>
+      <unconditional>N</unconditional>
+    </hop>
+    <hop>
+      <from>move to processing</from>
+      <to>empty source folder</to>
+      <enabled>Y</enabled>
+      <evaluation>Y</evaluation>
+      <unconditional>N</unconditional>
+    </hop>
+    <hop>
+      <from>empty source folder</from>
+      <to>5 files in processing</to>
+      <enabled>Y</enabled>
+      <evaluation>Y</evaluation>
+      <unconditional>N</unconditional>
+    </hop>
+    <hop>
+      <from>5 files in processing</from>
+      <to>move to archive</to>
+      <enabled>Y</enabled>
+      <evaluation>Y</evaluation>
+      <unconditional>N</unconditional>
+    </hop>
+    <hop>
+      <from>empty processing folder</from>
+      <to>5 files in archive</to>
+      <enabled>Y</enabled>
+      <evaluation>Y</evaluation>
+      <unconditional>N</unconditional>
+    </hop>
+    <hop>
+      <from>move to archive</from>
+      <to>empty processing folder</to>
+      <enabled>Y</enabled>
+      <evaluation>Y</evaluation>
+      <unconditional>N</unconditional>
+    </hop>
+    <hop>
+      <from>Unzip files-0015/files.zip</from>
+      <to>5 files in /tmp/action-0015/</to>
+      <enabled>Y</enabled>
+      <evaluation>Y</evaluation>
+      <unconditional>N</unconditional>
+    </hop>
+    <hop>
+      <from>5 files in /tmp/action-0015/</from>
+      <to>/tmp/action-0015/processing</to>
+      <enabled>Y</enabled>
+      <evaluation>Y</evaluation>
+      <unconditional>N</unconditional>
+    </hop>
+  </hops>
+  <notepads>
+  </notepads>
+  <attributes/>
+</workflow>
diff --git 
a/plugins/actions/movefiles/src/main/java/org/apache/hop/workflow/actions/movefiles/ActionMoveFiles.java
 
b/plugins/actions/movefiles/src/main/java/org/apache/hop/workflow/actions/movefiles/ActionMoveFiles.java
index 3be8cd15df..333865c82d 100644
--- 
a/plugins/actions/movefiles/src/main/java/org/apache/hop/workflow/actions/movefiles/ActionMoveFiles.java
+++ 
b/plugins/actions/movefiles/src/main/java/org/apache/hop/workflow/actions/movefiles/ActionMoveFiles.java
@@ -19,10 +19,13 @@ package org.apache.hop.workflow.actions.movefiles;
 
 import java.io.IOException;
 import java.text.SimpleDateFormat;
+import java.util.ArrayList;
 import java.util.Date;
 import java.util.List;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
+import lombok.Getter;
+import lombok.Setter;
 import org.apache.commons.vfs2.AllFileSelector;
 import org.apache.commons.vfs2.FileObject;
 import org.apache.commons.vfs2.FileSelectInfo;
@@ -35,12 +38,11 @@ import org.apache.hop.core.ResultFile;
 import org.apache.hop.core.RowMetaAndData;
 import org.apache.hop.core.annotations.Action;
 import org.apache.hop.core.exception.HopException;
-import org.apache.hop.core.exception.HopXmlException;
 import org.apache.hop.core.util.Utils;
 import org.apache.hop.core.variables.IVariables;
 import org.apache.hop.core.vfs.HopVfs;
-import org.apache.hop.core.xml.XmlHandler;
 import org.apache.hop.i18n.BaseMessages;
+import org.apache.hop.metadata.api.HopMetadataProperty;
 import org.apache.hop.metadata.api.IHopMetadataProvider;
 import org.apache.hop.workflow.WorkflowMeta;
 import org.apache.hop.workflow.action.ActionBase;
@@ -50,7 +52,6 @@ import 
org.apache.hop.workflow.action.validator.ActionValidatorUtils;
 import org.apache.hop.workflow.action.validator.AndValidator;
 import org.apache.hop.workflow.action.validator.ValidatorContext;
 import org.apache.hop.workflow.engine.IWorkflowEngine;
-import org.w3c.dom.Node;
 
 /** This defines a 'move files' action. */
 @Action(
@@ -61,6 +62,8 @@ import org.w3c.dom.Node;
     categoryDescription = 
"i18n:org.apache.hop.workflow:ActionCategory.Category.FileManagement",
     keywords = "i18n::ActionMoveFiles.keyword",
     documentationUrl = "/workflow/actions/movefiles.html")
+@Getter
+@Setter
 @SuppressWarnings("java:S1104")
 public class ActionMoveFiles extends ActionBase implements Cloneable, IAction {
   private static final Class<?> PKG = ActionMoveFiles.class;
@@ -74,38 +77,87 @@ public class ActionMoveFiles extends ActionBase implements 
Cloneable, IAction {
   public static final String 
CONST_ACTION_MOVE_FILES_ERROR_SUCCESS_CONDITIONBROKEN =
       "ActionMoveFiles.Error.SuccessConditionbroken";
 
-  public boolean moveEmptyFolders;
-  public boolean argFromPrevious;
-  public boolean includeSubfolders;
-  public boolean addResultFilenames;
-  public boolean destinationIsAFile;
-  public boolean createDestinationFolder;
-  public String[] sourceFileFolder;
-  public String[] destinationFileFolder;
-  public String[] wildcard;
-  private String nrErrorsLessThan;
-
-  private String successCondition;
   public static final String SUCCESS_IF_AT_LEAST_X_FILES_UN_ZIPPED = 
"success_when_at_least";
   public static final String SUCCESS_IF_ERRORS_LESS = "success_if_errors_less";
   public static final String SUCCESS_IF_NO_ERRORS = "success_if_no_errors";
+  public static final String MOVE_FILE = "move_file";
+  public static final String DELETE_FILE = "delete_file";
+  public static final String FAIL = "fail";
+
+  @HopMetadataProperty(key = "move_empty_folders")
+  private boolean moveEmptyFolders;
+
+  @HopMetadataProperty(key = "arg_from_previous")
+  private boolean argFromPrevious;
+
+  @HopMetadataProperty(key = "include_subfolders")
+  private boolean includeSubfolders;
+
+  @HopMetadataProperty(key = "add_result_filesname")
+  private boolean addResultFilenames;
+
+  @HopMetadataProperty(key = "destination_is_a_file")
+  private boolean destinationIsAFile;
+
+  @HopMetadataProperty(key = "create_destination_folder")
+  private boolean createDestinationFolder;
+
+  @HopMetadataProperty(key = "field", groupKey = "fields")
+  private List<FileToMove> filesToMove;
 
+  @HopMetadataProperty(key = "nr_errors_less_than")
+  private String nrErrorsLessThan;
+
+  @HopMetadataProperty(key = "success_condition")
+  private String successCondition;
+
+  @HopMetadataProperty(key = "add_date")
   private boolean addDate;
+
+  @HopMetadataProperty(key = "add_time")
   private boolean addTime;
+
+  @HopMetadataProperty(key = "SpecifyFormat")
   private boolean specifyFormat;
+
+  @HopMetadataProperty(key = "date_time_format")
   private String dateTimeFormat;
+
+  @HopMetadataProperty(key = "AddDateBeforeExtension")
   private boolean addDateBeforeExtension;
+
+  @HopMetadataProperty(key = "DoNotKeepFolderStructure")
   private boolean doNotKeepFolderStructure;
+
+  @HopMetadataProperty(key = "iffileexists")
   private String ifFileExists;
+
+  @HopMetadataProperty(key = "destinationFolder")
   private String destinationFolder;
+
+  @HopMetadataProperty(key = "ifmovedfileexists")
   private String ifMovedFileExists;
+
+  @HopMetadataProperty(key = "moved_date_time_format")
   private String movedDateTimeFormat;
+
+  @HopMetadataProperty(key = "AddMovedDateBeforeExtension")
   private boolean addMovedDateBeforeExtension;
+
+  @HopMetadataProperty(key = "add_moved_date")
   private boolean addMovedDate;
+
+  @HopMetadataProperty(key = "add_moved_time")
   private boolean addMovedTime;
+
+  @HopMetadataProperty(key = "SpecifyMoveFormat")
   private boolean specifyMoveFormat;
-  public boolean createMoveToFolder;
-  public boolean simulate;
+
+  @HopMetadataProperty(key = "create_move_to_folder")
+  private boolean createMoveToFolder;
+
+  @HopMetadataProperty(key = "simulate")
+  private boolean simulate;
 
   int nrErrors = 0;
   int nrSuccess = 0;
@@ -115,204 +167,60 @@ public class ActionMoveFiles extends ActionBase 
implements Cloneable, IAction {
 
   public ActionMoveFiles(String n) {
     super(n, "");
-    simulate = false;
-    createMoveToFolder = false;
-    specifyMoveFormat = false;
-    addMovedDate = false;
-    addMovedTime = false;
-    addMovedDateBeforeExtension = false;
-    movedDateTimeFormat = null;
+    filesToMove = new ArrayList<>();
     ifMovedFileExists = CONST_DO_NOTHING;
-    destinationFolder = null;
-    doNotKeepFolderStructure = false;
     moveEmptyFolders = true;
-    argFromPrevious = false;
-    sourceFileFolder = null;
-    destinationFileFolder = null;
-    wildcard = null;
-    includeSubfolders = false;
-    addResultFilenames = false;
-    destinationIsAFile = false;
-    createDestinationFolder = false;
     nrErrorsLessThan = "10";
     successCondition = SUCCESS_IF_NO_ERRORS;
-    addDate = false;
-    addTime = false;
-    specifyFormat = false;
-    dateTimeFormat = null;
-    addDateBeforeExtension = false;
-    ifFileExists = CONST_DO_NOTHING;
   }
 
   public ActionMoveFiles() {
     this("");
   }
 
-  public void allocate(int nrFields) {
-    sourceFileFolder = new String[nrFields];
-    destinationFileFolder = new String[nrFields];
-    wildcard = new String[nrFields];
+  public ActionMoveFiles(ActionMoveFiles a) {
+    super(a);
+    this.moveEmptyFolders = a.moveEmptyFolders;
+    this.argFromPrevious = a.argFromPrevious;
+    this.includeSubfolders = a.includeSubfolders;
+    this.addResultFilenames = a.addResultFilenames;
+    this.destinationIsAFile = a.destinationIsAFile;
+    this.createDestinationFolder = a.createDestinationFolder;
+    this.nrErrorsLessThan = a.nrErrorsLessThan;
+    this.successCondition = a.successCondition;
+    this.addDate = a.addDate;
+    this.addTime = a.addTime;
+    this.specifyFormat = a.specifyFormat;
+    this.dateTimeFormat = a.dateTimeFormat;
+    this.addDateBeforeExtension = a.addDateBeforeExtension;
+    this.doNotKeepFolderStructure = a.doNotKeepFolderStructure;
+    this.ifFileExists = a.ifFileExists;
+    this.destinationFolder = a.destinationFolder;
+    this.ifMovedFileExists = a.ifMovedFileExists;
+    this.movedDateTimeFormat = a.movedDateTimeFormat;
+    this.addMovedDateBeforeExtension = a.addMovedDateBeforeExtension;
+    this.addMovedDate = a.addMovedDate;
+    this.addMovedTime = a.addMovedTime;
+    this.specifyMoveFormat = a.specifyMoveFormat;
+    this.createMoveToFolder = a.createMoveToFolder;
+    this.simulate = a.simulate;
+    this.filesToMove = new ArrayList<>();
+    a.filesToMove.forEach(f -> filesToMove.add(new FileToMove(f)));
+
+    this.nrErrors = 0;
+    this.nrSuccess = 0;
+    this.successConditionBroken = false;
+    this.successConditionBrokenExit = false;
+    this.limitFiles = 0;
   }
 
   @Override
   public Object clone() {
-    ActionMoveFiles je = (ActionMoveFiles) super.clone();
-    if (sourceFileFolder != null) {
-      int nrFields = sourceFileFolder.length;
-      je.allocate(nrFields);
-      System.arraycopy(sourceFileFolder, 0, je.sourceFileFolder, 0, nrFields);
-      System.arraycopy(wildcard, 0, je.wildcard, 0, nrFields);
-      System.arraycopy(destinationFileFolder, 0, je.destinationFileFolder, 0, 
nrFields);
-    }
-    return je;
-  }
-
-  @Override
-  public String getXml() {
-    StringBuilder retval = new StringBuilder(600);
-
-    retval.append(super.getXml());
-    retval
-        .append(CONST_SPACES)
-        .append(XmlHandler.addTagValue("move_empty_folders", 
moveEmptyFolders));
-    retval
-        .append(CONST_SPACES)
-        .append(XmlHandler.addTagValue("arg_from_previous", argFromPrevious));
-    retval
-        .append(CONST_SPACES)
-        .append(XmlHandler.addTagValue("include_subfolders", 
includeSubfolders));
-    retval
-        .append(CONST_SPACES)
-        .append(XmlHandler.addTagValue("add_result_filesname", 
addResultFilenames));
-    retval
-        .append(CONST_SPACES)
-        .append(XmlHandler.addTagValue("destination_is_a_file", 
destinationIsAFile));
-    retval
-        .append(CONST_SPACES)
-        .append(XmlHandler.addTagValue("create_destination_folder", 
createDestinationFolder));
-    retval.append(CONST_SPACES).append(XmlHandler.addTagValue("add_date", 
addDate));
-    retval.append(CONST_SPACES).append(XmlHandler.addTagValue("add_time", 
addTime));
-    retval.append(CONST_SPACES).append(XmlHandler.addTagValue("SpecifyFormat", 
specifyFormat));
-    
retval.append(CONST_SPACES).append(XmlHandler.addTagValue("date_time_format", 
dateTimeFormat));
-    retval
-        .append(CONST_SPACES)
-        .append(XmlHandler.addTagValue("nr_errors_less_than", 
nrErrorsLessThan));
-    retval
-        .append(CONST_SPACES)
-        .append(XmlHandler.addTagValue("success_condition", successCondition));
-    retval
-        .append(CONST_SPACES)
-        .append(XmlHandler.addTagValue("AddDateBeforeExtension", 
addDateBeforeExtension));
-    retval
-        .append(CONST_SPACES)
-        .append(XmlHandler.addTagValue("DoNotKeepFolderStructure", 
doNotKeepFolderStructure));
-    retval.append(CONST_SPACES).append(XmlHandler.addTagValue("iffileexists", 
ifFileExists));
-    retval
-        .append(CONST_SPACES)
-        .append(XmlHandler.addTagValue("destinationFolder", 
destinationFolder));
-    retval
-        .append(CONST_SPACES)
-        .append(XmlHandler.addTagValue("ifmovedfileexists", 
ifMovedFileExists));
-    retval
-        .append(CONST_SPACES)
-        .append(XmlHandler.addTagValue("moved_date_time_format", 
movedDateTimeFormat));
-    retval
-        .append(CONST_SPACES)
-        .append(XmlHandler.addTagValue("create_move_to_folder", 
createMoveToFolder));
-    
retval.append(CONST_SPACES).append(XmlHandler.addTagValue("add_moved_date", 
addMovedDate));
-    
retval.append(CONST_SPACES).append(XmlHandler.addTagValue("add_moved_time", 
addMovedTime));
-    retval
-        .append(CONST_SPACES)
-        .append(XmlHandler.addTagValue("SpecifyMoveFormat", 
specifyMoveFormat));
-    retval
-        .append(CONST_SPACES)
-        .append(XmlHandler.addTagValue("AddMovedDateBeforeExtension", 
addMovedDateBeforeExtension));
-    retval.append(CONST_SPACES).append(XmlHandler.addTagValue("simulate", 
simulate));
-
-    retval.append("      <fields>").append(Const.CR);
-    if (sourceFileFolder != null) {
-      for (int i = 0; i < sourceFileFolder.length; i++) {
-        retval.append("        <field>").append(Const.CR);
-        retval
-            .append(CONST_SPACES_LONG)
-            .append(XmlHandler.addTagValue("source_filefolder", 
sourceFileFolder[i]));
-        retval
-            .append(CONST_SPACES_LONG)
-            .append(XmlHandler.addTagValue("destination_filefolder", 
destinationFileFolder[i]));
-        
retval.append(CONST_SPACES_LONG).append(XmlHandler.addTagValue("wildcard", 
wildcard[i]));
-        retval.append("        </field>").append(Const.CR);
-      }
-    }
-    retval.append("      </fields>").append(Const.CR);
-
-    return retval.toString();
-  }
-
-  @Override
-  public void loadXml(Node entrynode, IHopMetadataProvider metadataProvider, 
IVariables variables)
-      throws HopXmlException {
-    try {
-      super.loadXml(entrynode);
-      moveEmptyFolders =
-          "Y".equalsIgnoreCase(XmlHandler.getTagValue(entrynode, 
"move_empty_folders"));
-      argFromPrevious =
-          "Y".equalsIgnoreCase(XmlHandler.getTagValue(entrynode, 
"arg_from_previous"));
-      includeSubfolders =
-          "Y".equalsIgnoreCase(XmlHandler.getTagValue(entrynode, 
"include_subfolders"));
-      addResultFilenames =
-          "Y".equalsIgnoreCase(XmlHandler.getTagValue(entrynode, 
"add_result_filesname"));
-      destinationIsAFile =
-          "Y".equalsIgnoreCase(XmlHandler.getTagValue(entrynode, 
"destination_is_a_file"));
-      createDestinationFolder =
-          "Y".equalsIgnoreCase(XmlHandler.getTagValue(entrynode, 
"create_destination_folder"));
-      addDate = "Y".equalsIgnoreCase(XmlHandler.getTagValue(entrynode, 
"add_date"));
-      addTime = "Y".equalsIgnoreCase(XmlHandler.getTagValue(entrynode, 
"add_time"));
-      specifyFormat = "Y".equalsIgnoreCase(XmlHandler.getTagValue(entrynode, 
"SpecifyFormat"));
-      addDateBeforeExtension =
-          "Y".equalsIgnoreCase(XmlHandler.getTagValue(entrynode, 
"AddDateBeforeExtension"));
-      doNotKeepFolderStructure =
-          "Y".equalsIgnoreCase(XmlHandler.getTagValue(entrynode, 
"DoNotKeepFolderStructure"));
-      dateTimeFormat = XmlHandler.getTagValue(entrynode, "date_time_format");
-      nrErrorsLessThan = XmlHandler.getTagValue(entrynode, 
"nr_errors_less_than");
-      successCondition = XmlHandler.getTagValue(entrynode, 
"success_condition");
-      ifFileExists = XmlHandler.getTagValue(entrynode, "iffileexists");
-      destinationFolder = XmlHandler.getTagValue(entrynode, 
"destinationFolder");
-      ifMovedFileExists = XmlHandler.getTagValue(entrynode, 
"ifmovedfileexists");
-      movedDateTimeFormat = XmlHandler.getTagValue(entrynode, 
"moved_date_time_format");
-      addMovedDateBeforeExtension =
-          "Y".equalsIgnoreCase(XmlHandler.getTagValue(entrynode, 
"AddMovedDateBeforeExtension"));
-      createMoveToFolder =
-          "Y".equalsIgnoreCase(XmlHandler.getTagValue(entrynode, 
"create_move_to_folder"));
-      addMovedDate = "Y".equalsIgnoreCase(XmlHandler.getTagValue(entrynode, 
"add_moved_date"));
-      addMovedTime = "Y".equalsIgnoreCase(XmlHandler.getTagValue(entrynode, 
"add_moved_time"));
-      specifyMoveFormat =
-          "Y".equalsIgnoreCase(XmlHandler.getTagValue(entrynode, 
"SpecifyMoveFormat"));
-      simulate = "Y".equalsIgnoreCase(XmlHandler.getTagValue(entrynode, 
"simulate"));
-
-      Node fields = XmlHandler.getSubNode(entrynode, "fields");
-
-      // How many field arguments?
-      int nrFields = XmlHandler.countNodes(fields, "field");
-      allocate(nrFields);
-
-      // Read them all...
-      for (int i = 0; i < nrFields; i++) {
-        Node fnode = XmlHandler.getSubNodeByNr(fields, "field", i);
-
-        sourceFileFolder[i] = XmlHandler.getTagValue(fnode, 
"source_filefolder");
-        destinationFileFolder[i] = XmlHandler.getTagValue(fnode, 
"destination_filefolder");
-        wildcard[i] = XmlHandler.getTagValue(fnode, "wildcard");
-      }
-    } catch (HopXmlException xe) {
-
-      throw new HopXmlException(
-          BaseMessages.getString(PKG, 
"ActionMoveFiles.Error.Exception.UnableLoadXML"), xe);
-    }
+    return new ActionMoveFiles(this);
   }
 
   @Override
-  public Result execute(Result previousResult, int nr) throws HopException {
-    Result result = previousResult;
+  public Result execute(Result result, int nr) throws HopException {
     List<RowMetaAndData> rows = result.getRows();
     RowMetaAndData resultRow = null;
     result.setNrErrors(1);
@@ -335,18 +243,17 @@ public class ActionMoveFiles extends ActionBase 
implements Cloneable, IAction {
 
     String moveToFolder = resolve(destinationFolder);
     // Get source and destination files, also wildcard
-    String[] vSourceFileFolder = sourceFileFolder;
-    String[] vDestinationFileFolder = destinationFileFolder;
-    String[] vwildcard = wildcard;
+    List<FileToMove> vFilesToMove = new ArrayList<>();
+    for (FileToMove fileToMove : filesToMove) {
+      vFilesToMove.add(new FileToMove(fileToMove));
+    }
 
-    if (ifFileExists.equals("move_file")) {
+    if (MOVE_FILE.equals(ifFileExists)) {
       if (Utils.isEmpty(moveToFolder)) {
         logError(BaseMessages.getString(PKG, 
"ActionMoveFiles.Log.Error.MoveToFolderMissing"));
         return result;
       }
-      FileObject folder = null;
-      try {
-        folder = HopVfs.getFileObject(moveToFolder, getVariables());
+      try (FileObject folder = HopVfs.getFileObject(moveToFolder, 
getVariables())) {
         if (!folder.exists()) {
           if (isDetailed()) {
             logDetailed(
@@ -375,14 +282,6 @@ public class ActionMoveFiles extends ActionBase implements 
Cloneable, IAction {
                 moveToFolder,
                 e.getMessage()));
         return result;
-      } finally {
-        if (folder != null) {
-          try {
-            folder.close();
-          } catch (IOException ex) {
-            /* Ignore */
-          }
-        }
       }
     }
 
@@ -444,14 +343,17 @@ public class ActionMoveFiles extends ActionBase 
implements Cloneable, IAction {
                 BaseMessages.getString(
                     PKG,
                     "ActionMoveFiles.Log.IgnoringRow",
-                    vSourceFileFolder[iteration],
-                    vDestinationFileFolder[iteration],
-                    vwildcard[iteration]));
+                    vFilesToMove.get(iteration).getSourceFileFolder(),
+                    vFilesToMove.get(iteration).getDestinationFileFolder(),
+                    vFilesToMove.get(iteration).getWildcard()));
           }
         }
       }
-    } else if (vSourceFileFolder != null && vDestinationFileFolder != null) {
-      for (int i = 0; i < vSourceFileFolder.length && 
!parentWorkflow.isStopped(); i++) {
+    } else if (!vFilesToMove.isEmpty()) {
+      for (FileToMove vFileToMove : vFilesToMove) {
+        if (parentWorkflow.isStopped()) {
+          break;
+        }
         // Success condition broken?
         if (successConditionBroken) {
           if (!successConditionBrokenExit) {
@@ -465,22 +367,23 @@ public class ActionMoveFiles extends ActionBase 
implements Cloneable, IAction {
           return result;
         }
 
-        if (!Utils.isEmpty(vSourceFileFolder[i]) && 
!Utils.isEmpty(vDestinationFileFolder[i])) {
+        if (!Utils.isEmpty(vFileToMove.getSourceFileFolder())
+            && !Utils.isEmpty(vFileToMove.getDestinationFileFolder())) {
           // ok we can process this file/folder
           if (isDetailed()) {
             logDetailed(
                 BaseMessages.getString(
                     PKG,
                     "ActionMoveFiles.Log.ProcessingRow",
-                    vSourceFileFolder[i],
-                    vDestinationFileFolder[i],
-                    vwildcard[i]));
+                    vFileToMove.getSourceFileFolder(),
+                    vFileToMove.getDestinationFileFolder(),
+                    vFileToMove.getWildcard()));
           }
 
           if (!processFileFolder(
-              vSourceFileFolder[i],
-              vDestinationFileFolder[i],
-              vwildcard[i],
+              vFileToMove.getSourceFileFolder(),
+              vFileToMove.getDestinationFileFolder(),
+              vFileToMove.getWildcard(),
               parentWorkflow,
               result,
               moveToFolder)) {
@@ -493,9 +396,9 @@ public class ActionMoveFiles extends ActionBase implements 
Cloneable, IAction {
                 BaseMessages.getString(
                     PKG,
                     "ActionMoveFiles.Log.IgnoringRow",
-                    vSourceFileFolder[i],
-                    vDestinationFileFolder[i],
-                    vwildcard[i]));
+                    vFileToMove.getSourceFileFolder(),
+                    vFileToMove.getDestinationFileFolder(),
+                    vFileToMove.getWildcard()));
           }
         }
       }
@@ -525,16 +428,10 @@ public class ActionMoveFiles extends ActionBase 
implements Cloneable, IAction {
   }
 
   private boolean getSuccessStatus() {
-    boolean retval = false;
-
-    if ((nrErrors == 0 && getSuccessCondition().equals(SUCCESS_IF_NO_ERRORS))
+    return (nrErrors == 0 && 
getSuccessCondition().equals(SUCCESS_IF_NO_ERRORS))
         || (nrSuccess >= limitFiles
             && 
getSuccessCondition().equals(SUCCESS_IF_AT_LEAST_X_FILES_UN_ZIPPED))
-        || (nrErrors <= limitFiles && 
getSuccessCondition().equals(SUCCESS_IF_ERRORS_LESS))) {
-      retval = true;
-    }
-
-    return retval;
+        || (nrErrors <= limitFiles && 
getSuccessCondition().equals(SUCCESS_IF_ERRORS_LESS));
   }
 
   private boolean processFileFolder(
@@ -756,7 +653,7 @@ public class ActionMoveFiles extends ActionBase implements 
Cloneable, IAction {
               PKG,
               "ActionMoveFiles.Error.Exception.MoveProcess",
               realSourceFilefoldername,
-              destinationFileFolder.toString(),
+              destinationFileFolder == null ? "" : 
destinationFileFolder.toString(),
               e.getMessage()));
     } finally {
       if (sourceFileFolder != null) {
@@ -910,7 +807,7 @@ public class ActionMoveFiles extends ActionBase implements 
Cloneable, IAction {
             updateSuccess();
             retVal = true;
           }
-          case "delete_file" -> {
+          case DELETE_FILE -> {
             if (!simulate) {
               sourceFileFolder.delete();
             }
@@ -1019,13 +916,13 @@ public class ActionMoveFiles extends ActionBase 
implements Cloneable, IAction {
                   updateSuccess();
                   retVal = true;
                 }
-                case "fail" ->
+                case FAIL ->
                     // Update Errors
                     updateErrors();
               }
             }
           }
-          case "fail" ->
+          case FAIL ->
               // Update Errors
               updateErrors();
           case CONST_DO_NOTHING -> retVal = true;
@@ -1059,7 +956,7 @@ public class ActionMoveFiles extends ActionBase implements 
Cloneable, IAction {
       String realWildcard,
       IWorkflowEngine<WorkflowMeta> parentWorkflow,
       Result result,
-      FileObject movetoFolderFolder) {
+      FileObject moveToFolderFolder) {
     boolean entryStatus = false;
     FileObject filename = null;
 
@@ -1088,9 +985,7 @@ public class ActionMoveFiles extends ActionBase implements 
Cloneable, IAction {
         String shortFilenameFromBaseFolder = shortDestinationFilename;
         if (!isDoNotKeepFolderStructure()) {
           shortFilenameFromBaseFolder =
-              currentFile
-                  .toString()
-                  .substring(sourceFileFolder.toString().length(), 
currentFile.toString().length());
+              
currentFile.toString().substring(sourceFileFolder.toString().length());
         }
         shortFilenameFromBaseFolder =
             shortFilenameFromBaseFolder.substring(
@@ -1104,30 +999,28 @@ public class ActionMoveFiles extends ActionBase 
implements Cloneable, IAction {
                 getVariables());
 
         if 
(!currentFile.getParent().toString().equals(sourceFileFolder.toString())) {
-
           // Not in the Base Folder..Only if include sub folders
           if (includeSubfolders) {
-            // Folders..only if include subfolders
+            // Folders... only if include subfolders
             if (currentFile.getType() == FileType.FOLDER) {
-              if (includeSubfolders && moveEmptyFolders && 
Utils.isEmpty(wildcard)) {
+              if (includeSubfolders && moveEmptyFolders && 
Utils.isEmpty(realWildcard)) {
                 entryStatus =
                     moveFile(
                         shortDestinationFilename,
                         currentFile,
                         filename,
-                        movetoFolderFolder,
+                        moveToFolderFolder,
                         parentWorkflow,
                         result);
               }
             } else {
-
               if (getFileWildcard(sourceShortFilename, realWildcard)) {
                 entryStatus =
                     moveFile(
                         shortDestinationFilename,
                         currentFile,
                         filename,
-                        movetoFolderFolder,
+                        moveToFolderFolder,
                         parentWorkflow,
                         result);
               }
@@ -1137,18 +1030,17 @@ public class ActionMoveFiles extends ActionBase 
implements Cloneable, IAction {
           // In the Base Folder...
           // Folders..only if include subfolders
           if (currentFile.getType() == FileType.FOLDER) {
-            if (includeSubfolders && moveEmptyFolders && 
Utils.isEmpty(wildcard)) {
+            if (includeSubfolders && moveEmptyFolders && 
Utils.isEmpty(realWildcard)) {
               entryStatus =
                   moveFile(
                       shortDestinationFilename,
                       currentFile,
                       filename,
-                      movetoFolderFolder,
+                      moveToFolderFolder,
                       parentWorkflow,
                       result);
             }
           } else {
-
             // file...Check if exists
             if (getFileWildcard(sourceShortFilename, realWildcard)) {
               entryStatus =
@@ -1156,7 +1048,7 @@ public class ActionMoveFiles extends ActionBase 
implements Cloneable, IAction {
                       shortDestinationFilename,
                       currentFile,
                       filename,
-                      movetoFolderFolder,
+                      moveToFolderFolder,
                       parentWorkflow,
                       result);
             }
@@ -1164,7 +1056,6 @@ public class ActionMoveFiles extends ActionBase 
implements Cloneable, IAction {
         }
       }
       entryStatus = true;
-
     } catch (Exception e) {
       logError(BaseMessages.getString(PKG, "ActionMoveFiles.Log.Error", 
e.toString()));
     } finally {
@@ -1189,12 +1080,8 @@ public class ActionMoveFiles extends ActionBase 
implements Cloneable, IAction {
   }
 
   private boolean checkIfSuccessConditionBroken() {
-    boolean retval = false;
-    if ((nrErrors > 0 && getSuccessCondition().equals(SUCCESS_IF_NO_ERRORS))
-        || (nrErrors >= limitFiles && 
getSuccessCondition().equals(SUCCESS_IF_ERRORS_LESS))) {
-      retval = true;
-    }
-    return retval;
+    return (nrErrors > 0 && getSuccessCondition().equals(SUCCESS_IF_NO_ERRORS))
+        || (nrErrors >= limitFiles && 
getSuccessCondition().equals(SUCCESS_IF_ERRORS_LESS));
   }
 
   private void updateSuccess() {
@@ -1202,12 +1089,12 @@ public class ActionMoveFiles extends ActionBase 
implements Cloneable, IAction {
   }
 
   private void addFileToResultFilenames(
-      String fileaddentry, Result result, IWorkflowEngine<WorkflowMeta> 
parentWorkflow) {
+      String fileAddEntry, Result result, IWorkflowEngine<WorkflowMeta> 
parentWorkflow) {
     try {
       ResultFile resultFile =
           new ResultFile(
               ResultFile.FILE_TYPE_GENERAL,
-              HopVfs.getFileObject(fileaddentry, getVariables()),
+              HopVfs.getFileObject(fileAddEntry, getVariables()),
               parentWorkflow.getWorkflowName(),
               toString());
       result.getResultFiles().put(resultFile.getFile().toString(), resultFile);
@@ -1215,13 +1102,14 @@ public class ActionMoveFiles extends ActionBase 
implements Cloneable, IAction {
       if (isDebug()) {
         logDebug(
             BaseMessages.getString(
-                PKG, "ActionMoveFiles.Log.FileAddedToResultFilenames", 
fileaddentry));
+                PKG, "ActionMoveFiles.Log.FileAddedToResultFilenames", 
fileAddEntry));
       }
 
     } catch (Exception e) {
       logError(
           BaseMessages.getString(PKG, 
"ActionMoveFiles.Error.AddingToFilenameResult"),
-          fileaddentry + "" + e.getMessage());
+          fileAddEntry + e.getMessage(),
+          e);
     }
   }
 
@@ -1270,7 +1158,9 @@ public class ActionMoveFiles extends ActionBase 
implements Cloneable, IAction {
     } catch (Exception e) {
       logError(
           BaseMessages.getString(
-              PKG, "ActionMoveFiles.Log.CanNotCreateParentFolder", 
folder.getName().toString()),
+              PKG,
+              "ActionMoveFiles.Log.CanNotCreateParentFolder",
+              (folder == null ? "" : folder.getName().toString())),
           e);
 
     } finally {
@@ -1287,9 +1177,9 @@ public class ActionMoveFiles extends ActionBase 
implements Cloneable, IAction {
 
   /**********************************************************
    *
-   * @param selectedfile
-   * @param wildcard
-   * @return True if the selectedfile matches the wildcard
+   * @param selectedfile The selected file
+   * @param wildcard The wildcard
+   * @return True if the selected file matches the wildcard
    **********************************************************/
   private boolean getFileWildcard(String selectedfile, String wildcard) {
     Pattern pattern = null;
@@ -1298,25 +1188,23 @@ public class ActionMoveFiles extends ActionBase 
implements Cloneable, IAction {
     if (!Utils.isEmpty(wildcard)) {
       pattern = Pattern.compile(wildcard);
       // First see if the file matches the regular expression!
-      if (pattern != null) {
-        Matcher matcher = pattern.matcher(selectedfile);
-        getIt = matcher.matches();
-      }
+      Matcher matcher = pattern.matcher(selectedfile);
+      getIt = matcher.matches();
     }
 
     return getIt;
   }
 
-  private String getDestinationFilename(String shortsourcefilename) {
-    String shortfilename = shortsourcefilename;
-    int lenstring = shortsourcefilename.length();
-    int lastindexOfDot = shortfilename.lastIndexOf('.');
-    if (lastindexOfDot == -1) {
-      lastindexOfDot = lenstring;
+  private String getDestinationFilename(String shortSourceFilename) {
+    String shortFilename = shortSourceFilename;
+    int stringLength = shortSourceFilename.length();
+    int lastIndexOfDot = shortFilename.lastIndexOf('.');
+    if (lastIndexOfDot == -1) {
+      lastIndexOfDot = stringLength;
     }
 
     if (isAddDateBeforeExtension()) {
-      shortfilename = shortfilename.substring(0, lastindexOfDot);
+      shortFilename = shortFilename.substring(0, lastIndexOfDot);
     }
 
     SimpleDateFormat daf = new SimpleDateFormat();
@@ -1325,36 +1213,36 @@ public class ActionMoveFiles extends ActionBase 
implements Cloneable, IAction {
     if (isSpecifyFormat() && !Utils.isEmpty(getDateTimeFormat())) {
       daf.applyPattern(getDateTimeFormat());
       String dt = daf.format(now);
-      shortfilename += dt;
+      shortFilename += dt;
     } else {
       if (isAddDate()) {
         daf.applyPattern("yyyyMMdd");
         String d = daf.format(now);
-        shortfilename += "_" + d;
+        shortFilename += "_" + d;
       }
       if (isAddTime()) {
         daf.applyPattern("HHmmssSSS");
         String t = daf.format(now);
-        shortfilename += "_" + t;
+        shortFilename += "_" + t;
       }
     }
     if (isAddDateBeforeExtension()) {
-      shortfilename += shortsourcefilename.substring(lastindexOfDot, 
lenstring);
+      shortFilename += shortSourceFilename.substring(lastIndexOfDot, 
stringLength);
     }
 
-    return shortfilename;
+    return shortFilename;
   }
 
-  private String getMoveDestinationFilename(String shortsourcefilename, String 
dateFormat) {
-    String shortfilename = shortsourcefilename;
-    int lenstring = shortsourcefilename.length();
-    int lastindexOfDot = shortfilename.lastIndexOf('.');
-    if (lastindexOfDot == -1) {
-      lastindexOfDot = lenstring;
+  private String getMoveDestinationFilename(String shortSourceFilename, String 
dateFormat) {
+    String shortFilename = shortSourceFilename;
+    int stringLength = shortSourceFilename.length();
+    int lastIndexOfDot = shortFilename.lastIndexOf('.');
+    if (lastIndexOfDot == -1) {
+      lastIndexOfDot = stringLength;
     }
 
     if (isAddMovedDateBeforeExtension()) {
-      shortfilename = shortfilename.substring(0, lastindexOfDot);
+      shortFilename = shortFilename.substring(0, lastIndexOfDot);
     }
 
     SimpleDateFormat daf = new SimpleDateFormat();
@@ -1363,191 +1251,30 @@ public class ActionMoveFiles extends ActionBase 
implements Cloneable, IAction {
     if (dateFormat != null) {
       daf.applyPattern(dateFormat);
       String dt = daf.format(now);
-      shortfilename += dt;
+      shortFilename += dt;
     } else {
-
       if (isSpecifyMoveFormat() && !Utils.isEmpty(getMovedDateTimeFormat())) {
         daf.applyPattern(getMovedDateTimeFormat());
         String dt = daf.format(now);
-        shortfilename += dt;
+        shortFilename += dt;
       } else {
         if (isAddMovedDate()) {
           daf.applyPattern("yyyyMMdd");
           String d = daf.format(now);
-          shortfilename += "_" + d;
+          shortFilename += "_" + d;
         }
         if (isAddMovedTime()) {
           daf.applyPattern("HHmmssSSS");
           String t = daf.format(now);
-          shortfilename += "_" + t;
+          shortFilename += "_" + t;
         }
       }
     }
     if (isAddMovedDateBeforeExtension()) {
-      shortfilename += shortsourcefilename.substring(lastindexOfDot, 
lenstring);
+      shortFilename += shortSourceFilename.substring(lastIndexOfDot, 
stringLength);
     }
 
-    return shortfilename;
-  }
-
-  public void setAddDate(boolean adddate) {
-    this.addDate = adddate;
-  }
-
-  public boolean isAddDate() {
-    return addDate;
-  }
-
-  public boolean isAddMovedDate() {
-    return addMovedDate;
-  }
-
-  public void setAddMovedDate(boolean addMovedDate) {
-    this.addMovedDate = addMovedDate;
-  }
-
-  public boolean isAddMovedTime() {
-    return addMovedTime;
-  }
-
-  public void setAddMovedTime(boolean addMovedTime) {
-    this.addMovedTime = addMovedTime;
-  }
-
-  public void setIfFileExists(String ifFileExists) {
-    this.ifFileExists = ifFileExists;
-  }
-
-  public String getIfFileExists() {
-    return ifFileExists;
-  }
-
-  public void setIfMovedFileExists(String ifMovedFileExists) {
-    this.ifMovedFileExists = ifMovedFileExists;
-  }
-
-  public String getIfMovedFileExists() {
-    return ifMovedFileExists;
-  }
-
-  public void setAddTime(boolean addtime) {
-    this.addTime = addtime;
-  }
-
-  public boolean isAddTime() {
-    return addTime;
-  }
-
-  public void setAddDateBeforeExtension(boolean addDateBeforeExtension) {
-    this.addDateBeforeExtension = addDateBeforeExtension;
-  }
-
-  public void setAddMovedDateBeforeExtension(boolean 
addMovedDateBeforeExtension) {
-    this.addMovedDateBeforeExtension = addMovedDateBeforeExtension;
-  }
-
-  public boolean isSpecifyFormat() {
-    return specifyFormat;
-  }
-
-  public void setSpecifyFormat(boolean specifyFormat) {
-    this.specifyFormat = specifyFormat;
-  }
-
-  public void setSpecifyMoveFormat(boolean specifyMoveFormat) {
-    this.specifyMoveFormat = specifyMoveFormat;
-  }
-
-  public boolean isSpecifyMoveFormat() {
-    return specifyMoveFormat;
-  }
-
-  public String getDateTimeFormat() {
-    return dateTimeFormat;
-  }
-
-  public void setDateTimeFormat(String dateTimeFormat) {
-    this.dateTimeFormat = dateTimeFormat;
-  }
-
-  public String getMovedDateTimeFormat() {
-    return movedDateTimeFormat;
-  }
-
-  public void setMovedDateTimeFormat(String movedDateTimeFormat) {
-    this.movedDateTimeFormat = movedDateTimeFormat;
-  }
-
-  public boolean isAddDateBeforeExtension() {
-    return addDateBeforeExtension;
-  }
-
-  public boolean isAddMovedDateBeforeExtension() {
-    return addMovedDateBeforeExtension;
-  }
-
-  public boolean isDoNotKeepFolderStructure() {
-    return doNotKeepFolderStructure;
-  }
-
-  public void setDestinationFolder(String destinationFolder) {
-    this.destinationFolder = destinationFolder;
-  }
-
-  public String getDestinationFolder() {
-    return destinationFolder;
-  }
-
-  public void setDoNotKeepFolderStructure(boolean doNotKeepFolderStructure) {
-    this.doNotKeepFolderStructure = doNotKeepFolderStructure;
-  }
-
-  public void setMoveEmptyFolders(boolean moveEmptyFolders) {
-    this.moveEmptyFolders = moveEmptyFolders;
-  }
-
-  public void setIncludeSubfolders(boolean includeSubfolders) {
-    this.includeSubfolders = includeSubfolders;
-  }
-
-  public void setAddresultfilesname(boolean addResultFilenames) {
-    this.addResultFilenames = addResultFilenames;
-  }
-
-  public void setArgFromPrevious(boolean argfrompreviousin) {
-    this.argFromPrevious = argfrompreviousin;
-  }
-
-  public void setDestinationIsAFile(boolean destinationIsAFile) {
-    this.destinationIsAFile = destinationIsAFile;
-  }
-
-  public void setCreateDestinationFolder(boolean createDestinationFolder) {
-    this.createDestinationFolder = createDestinationFolder;
-  }
-
-  public void setCreateMoveToFolder(boolean createMoveToFolder) {
-    this.createMoveToFolder = createMoveToFolder;
-  }
-
-  public void setNrErrorsLessThan(String nrErrorsLessThan) {
-    this.nrErrorsLessThan = nrErrorsLessThan;
-  }
-
-  public String getNrErrorsLessThan() {
-    return nrErrorsLessThan;
-  }
-
-  public void setSimulate(boolean simulate) {
-    this.simulate = simulate;
-  }
-
-  public void setSuccessCondition(String successCondition) {
-    this.successCondition = successCondition;
-  }
-
-  public String getSuccessCondition() {
-    return successCondition;
+    return shortFilename;
   }
 
   @Override
@@ -1564,7 +1291,7 @@ public class ActionMoveFiles extends ActionBase 
implements Cloneable, IAction {
                 remarks,
                 
AndValidator.putValidators(ActionValidatorUtils.notNullValidator()));
 
-    if (res == false) {
+    if (!res) {
       return;
     }
 
@@ -1573,7 +1300,7 @@ public class ActionMoveFiles extends ActionBase 
implements Cloneable, IAction {
     AndValidator.putValidators(
         ctx, ActionValidatorUtils.notNullValidator(), 
ActionValidatorUtils.fileExistsValidator());
 
-    for (int i = 0; i < sourceFileFolder.length; i++) {
+    for (int i = 0; i < filesToMove.size(); i++) {
       ActionValidatorUtils.andValidator().validate(this, "arguments[" + i + 
"]", remarks, ctx);
     }
   }
@@ -1603,4 +1330,26 @@ public class ActionMoveFiles extends ActionBase 
implements Cloneable, IAction {
 
     folder.createFolder();
   }
+
+  @Getter
+  @Setter
+  public static final class FileToMove {
+    @HopMetadataProperty(key = "source_filefolder")
+    private String sourceFileFolder;
+
+    @HopMetadataProperty(key = "destination_filefolder")
+    private String destinationFileFolder;
+
+    @HopMetadataProperty(key = "wildcard")
+    private String wildcard;
+
+    public FileToMove() {}
+
+    public FileToMove(FileToMove f) {
+      this();
+      this.sourceFileFolder = f.sourceFileFolder;
+      this.destinationFileFolder = f.destinationFileFolder;
+      this.wildcard = f.wildcard;
+    }
+  }
 }
diff --git 
a/plugins/actions/movefiles/src/main/java/org/apache/hop/workflow/actions/movefiles/ActionMoveFilesDialog.java
 
b/plugins/actions/movefiles/src/main/java/org/apache/hop/workflow/actions/movefiles/ActionMoveFilesDialog.java
index 8f87b356ee..a4db1a7d99 100644
--- 
a/plugins/actions/movefiles/src/main/java/org/apache/hop/workflow/actions/movefiles/ActionMoveFilesDialog.java
+++ 
b/plugins/actions/movefiles/src/main/java/org/apache/hop/workflow/actions/movefiles/ActionMoveFilesDialog.java
@@ -264,7 +264,7 @@ public class ActionMoveFilesDialog extends ActionDialog {
     wlPrevious.setLayoutData(fdlPrevious);
     wPrevious = new Button(wSettings, SWT.CHECK);
     PropsUi.setLook(wPrevious);
-    wPrevious.setSelection(action.argFromPrevious);
+    wPrevious.setSelection(action.isArgFromPrevious());
     wPrevious.setToolTipText(BaseMessages.getString(PKG, 
"ActionMoveFiles.Previous.Tooltip"));
     FormData fdPrevious = new FormData();
     fdPrevious.left = new FormAttachment(middle, 0);
@@ -291,12 +291,7 @@ public class ActionMoveFilesDialog extends ActionDialog {
     fdlFields.top = new FormAttachment(wSettings, margin);
     wlFields.setLayoutData(fdlFields);
 
-    int rows =
-        action.sourceFileFolder == null
-            ? 1
-            : (action.sourceFileFolder.length == 0 ? 0 : 
action.sourceFileFolder.length);
-
-    ColumnInfo[] colinf =
+    ColumnInfo[] columnInfos =
         new ColumnInfo[] {
           new ColumnInfo(
               BaseMessages.getString(PKG, 
"ActionMoveFiles.Fields.SourceFileFolder.Label"),
@@ -312,24 +307,25 @@ public class ActionMoveFilesDialog extends ActionDialog {
               false),
         };
 
-    colinf[0].setUsingVariables(true);
-    colinf[0].setToolTip(
+    columnInfos[0].setUsingVariables(true);
+    columnInfos[0].setToolTip(
         BaseMessages.getString(PKG, 
"ActionMoveFiles.Fields.SourceFileFolder.Tooltip"));
-    colinf[0].setTextVarButtonSelectionListener(getFileSelectionAdapter());
-    colinf[1].setUsingVariables(true);
-    colinf[1].setToolTip(
+    
columnInfos[0].setTextVarButtonSelectionListener(getFileSelectionAdapter());
+    columnInfos[1].setUsingVariables(true);
+    columnInfos[1].setToolTip(
         BaseMessages.getString(PKG, 
"ActionMoveFiles.Fields.DestinationFileFolder.Tooltip"));
-    colinf[1].setTextVarButtonSelectionListener(getFileSelectionAdapter());
-    colinf[2].setUsingVariables(true);
-    colinf[2].setToolTip(BaseMessages.getString(PKG, 
"ActionMoveFiles.Fields.Wildcard.Tooltip"));
+    
columnInfos[1].setTextVarButtonSelectionListener(getFileSelectionAdapter());
+    columnInfos[2].setUsingVariables(true);
+    columnInfos[2].setToolTip(
+        BaseMessages.getString(PKG, 
"ActionMoveFiles.Fields.Wildcard.Tooltip"));
 
     wFields =
         new TableView(
             variables,
             wGeneralComp,
             SWT.BORDER | SWT.FULL_SELECTION | SWT.MULTI,
-            colinf,
-            rows,
+            columnInfos,
+            1,
             lsMod,
             props);
 
@@ -366,13 +362,13 @@ public class ActionMoveFilesDialog extends ActionDialog {
     wDestinationFileTab.setText(
         BaseMessages.getString(PKG, 
"ActionMoveFiles.DestinationFileTab.Label"));
 
-    FormLayout destcontentLayout = new FormLayout();
-    destcontentLayout.marginWidth = 3;
-    destcontentLayout.marginHeight = 3;
+    FormLayout destinationContentLayout = new FormLayout();
+    destinationContentLayout.marginWidth = 3;
+    destinationContentLayout.marginHeight = 3;
 
     Composite wDestinationFileComp = new Composite(wTabFolder, SWT.NONE);
     PropsUi.setLook(wDestinationFileComp);
-    wDestinationFileComp.setLayout(destcontentLayout);
+    wDestinationFileComp.setLayout(destinationContentLayout);
 
     // DestinationFile grouping?
     // ////////////////////////
@@ -1170,38 +1166,26 @@ public class ActionMoveFilesDialog extends ActionDialog 
{
   /** Copy information from the meta-data input to the dialog fields. */
   public void getData() {
     wName.setText(Const.NVL(action.getName(), ""));
-    wMoveEmptyFolders.setSelection(action.moveEmptyFolders);
+    wMoveEmptyFolders.setSelection(action.isMoveEmptyFolders());
 
-    if (action.sourceFileFolder != null) {
-      for (int i = 0; i < action.sourceFileFolder.length; i++) {
-        TableItem ti = wFields.table.getItem(i);
-        if (action.sourceFileFolder[i] != null) {
-          ti.setText(1, action.sourceFileFolder[i]);
-        }
-        if (action.destinationFileFolder[i] != null) {
-          ti.setText(2, action.destinationFileFolder[i]);
-        }
-        if (action.wildcard[i] != null) {
-          ti.setText(3, action.wildcard[i]);
-        }
-      }
-      wFields.setRowNums();
-      wFields.optWidth(true);
+    for (ActionMoveFiles.FileToMove fileToMove : action.getFilesToMove()) {
+      TableItem ti = new TableItem(wFields.table, SWT.NONE);
+      ti.setText(1, Const.NVL(fileToMove.getSourceFileFolder(), ""));
+      ti.setText(2, Const.NVL(fileToMove.getDestinationFileFolder(), ""));
+      ti.setText(3, Const.NVL(fileToMove.getWildcard(), ""));
     }
-    wPrevious.setSelection(action.argFromPrevious);
-    wIncludeSubfolders.setSelection(action.includeSubfolders);
-    wDestinationIsAFile.setSelection(action.destinationIsAFile);
-    wCreateDestinationFolder.setSelection(action.createDestinationFolder);
+    wFields.optimizeTableView();
 
-    wAddFileToResult.setSelection(action.addResultFilenames);
+    wPrevious.setSelection(action.isArgFromPrevious());
+    wIncludeSubfolders.setSelection(action.isIncludeSubfolders());
+    wDestinationIsAFile.setSelection(action.isDestinationIsAFile());
+    wCreateDestinationFolder.setSelection(action.isCreateDestinationFolder());
 
-    wCreateMoveToFolder.setSelection(action.createMoveToFolder);
+    wAddFileToResult.setSelection(action.isAddResultFilenames());
 
-    if (action.getNrErrorsLessThan() != null) {
-      wNrErrorsLessThan.setText(action.getNrErrorsLessThan());
-    } else {
-      wNrErrorsLessThan.setText("10");
-    }
+    wCreateMoveToFolder.setSelection(action.isCreateMoveToFolder());
+
+    wNrErrorsLessThan.setText(Const.NVL(action.getNrErrorsLessThan(), "10"));
 
     if (action.getSuccessCondition() != null) {
       if (action
@@ -1221,18 +1205,16 @@ public class ActionMoveFilesDialog extends ActionDialog 
{
       switch (action.getIfFileExists()) {
         case CONST_OVERWRITE_FILE -> wIfFileExists.select(1);
         case CONST_UNIQUE_NAME -> wIfFileExists.select(2);
-        case "delete_file" -> wIfFileExists.select(3);
-        case "move_file" -> wIfFileExists.select(4);
-        case "fail" -> wIfFileExists.select(5);
+        case ActionMoveFiles.DELETE_FILE -> wIfFileExists.select(3);
+        case ActionMoveFiles.MOVE_FILE -> wIfFileExists.select(4);
+        case ActionMoveFiles.FAIL -> wIfFileExists.select(5);
         default -> wIfFileExists.select(0);
       }
     } else {
       wIfFileExists.select(0);
     }
 
-    if (action.getDestinationFolder() != null) {
-      wDestinationFolder.setText(action.getDestinationFolder());
-    }
+    wDestinationFolder.setText(Const.NVL(action.getDestinationFolder(), ""));
 
     if (action.getIfMovedFileExists() != null) {
       switch (action.getIfMovedFileExists()) {
@@ -1246,21 +1228,17 @@ public class ActionMoveFilesDialog extends ActionDialog 
{
     }
     
wDoNotKeepFolderStructure.setSelection(action.isDoNotKeepFolderStructure());
     wAddDateBeforeExtension.setSelection(action.isAddDateBeforeExtension());
-    wSimulate.setSelection(action.simulate);
+    wSimulate.setSelection(action.isSimulate());
 
     wAddDate.setSelection(action.isAddDate());
     wAddTime.setSelection(action.isAddTime());
     wSpecifyFormat.setSelection(action.isSpecifyFormat());
-    if (action.getDateTimeFormat() != null) {
-      wDateTimeFormat.setText(action.getDateTimeFormat());
-    }
+    wDateTimeFormat.setText(Const.NVL(action.getDateTimeFormat(), ""));
 
     wAddMovedDate.setSelection(action.isAddMovedDate());
     wAddMovedTime.setSelection(action.isAddMovedTime());
     wSpecifyMoveFormat.setSelection(action.isSpecifyMoveFormat());
-    if (action.getMovedDateTimeFormat() != null) {
-      wMovedDateTimeFormat.setText(action.getMovedDateTimeFormat());
-    }
+    wMovedDateTimeFormat.setText(Const.NVL(action.getMovedDateTimeFormat(), 
""));
     
wAddMovedDateBeforeExtension.setSelection(action.isAddMovedDateBeforeExtension());
   }
 
@@ -1287,7 +1265,7 @@ public class ActionMoveFilesDialog extends ActionDialog {
     action.setMoveEmptyFolders(wMoveEmptyFolders.getSelection());
     action.setIncludeSubfolders(wIncludeSubfolders.getSelection());
     action.setArgFromPrevious(wPrevious.getSelection());
-    action.setAddresultfilesname(wAddFileToResult.getSelection());
+    action.setAddResultFilenames(wAddFileToResult.getSelection());
     action.setDestinationIsAFile(wDestinationIsAFile.getSelection());
     action.setCreateDestinationFolder(wCreateDestinationFolder.getSelection());
     action.setNrErrorsLessThan(wNrErrorsLessThan.getText());
@@ -1343,29 +1321,16 @@ public class ActionMoveFilesDialog extends ActionDialog 
{
     action.setMovedDateTimeFormat(wMovedDateTimeFormat.getText());
     
action.setAddMovedDateBeforeExtension(wAddMovedDateBeforeExtension.getSelection());
 
-    int nrItems = wFields.nrNonEmpty();
-    int nr = 0;
-    for (int i = 0; i < nrItems; i++) {
-      String arg = wFields.getNonEmpty(i).getText(1);
-      if (!Utils.isEmpty(arg)) {
-        nr++;
-      }
-    }
-    action.sourceFileFolder = new String[nr];
-    action.destinationFileFolder = new String[nr];
-    action.wildcard = new String[nr];
-    nr = 0;
-    for (int i = 0; i < nrItems; i++) {
-      String source = wFields.getNonEmpty(i).getText(1);
-      String dest = wFields.getNonEmpty(i).getText(2);
-      String wild = wFields.getNonEmpty(i).getText(3);
-      if (!Utils.isEmpty(source)) {
-        action.sourceFileFolder[nr] = source;
-        action.destinationFileFolder[nr] = dest;
-        action.wildcard[nr] = wild;
-        nr++;
-      }
+    action.getFilesToMove().clear();
+    for (TableItem item : wFields.getNonEmptyItems()) {
+      ActionMoveFiles.FileToMove fileToMove = new ActionMoveFiles.FileToMove();
+      action.getFilesToMove().add(fileToMove);
+
+      fileToMove.setSourceFileFolder(item.getText(1));
+      fileToMove.setDestinationFileFolder(item.getText(2));
+      fileToMove.setWildcard(item.getText(3));
     }
+
     dispose();
   }
 }
diff --git 
a/plugins/actions/movefiles/src/test/java/org/apache/hop/workflow/actions/movefiles/ActionMoveFilesTest.java
 
b/plugins/actions/movefiles/src/test/java/org/apache/hop/workflow/actions/movefiles/ActionMoveFilesTest.java
new file mode 100644
index 0000000000..85255081b3
--- /dev/null
+++ 
b/plugins/actions/movefiles/src/test/java/org/apache/hop/workflow/actions/movefiles/ActionMoveFilesTest.java
@@ -0,0 +1,75 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.hop.workflow.actions.movefiles;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import org.apache.hop.core.HopClientEnvironment;
+import org.apache.hop.workflow.action.ActionSerializationTestUtil;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+class ActionMoveFilesTest {
+  @BeforeEach
+  void beforeEach() throws Exception {
+    HopClientEnvironment.init();
+  }
+
+  @Test
+  void testSerializationRoundTrip() throws Exception {
+    ActionMoveFiles action =
+        ActionSerializationTestUtil.testSerialization(
+            "/action-move-files.xml", ActionMoveFiles.class);
+
+    assertTrue(action.isMoveEmptyFolders());
+    assertTrue(action.isArgFromPrevious());
+    assertTrue(action.isIncludeSubfolders());
+    assertTrue(action.isAddResultFilenames());
+    assertTrue(action.isDestinationIsAFile());
+    assertTrue(action.isCreateDestinationFolder());
+    assertTrue(action.isAddDate());
+    assertTrue(action.isAddTime());
+    assertTrue(action.isSpecifyFormat());
+    assertTrue(action.isAddDateBeforeExtension());
+    assertTrue(action.isDoNotKeepFolderStructure());
+    assertTrue(action.isCreateMoveToFolder());
+    assertTrue(action.isAddMovedDate());
+    assertTrue(action.isAddMovedTime());
+    assertTrue(action.isSpecifyMoveFormat());
+    assertTrue(action.isAddMovedDateBeforeExtension());
+    assertTrue(action.isSimulate());
+    assertEquals("dt-format", action.getDateTimeFormat());
+    assertEquals("10", action.getNrErrorsLessThan());
+    assertEquals("success_if_no_errors", action.getSuccessCondition());
+    assertEquals("overwrite_file", action.getIfFileExists());
+    assertEquals("destination-folder", action.getDestinationFolder());
+    assertEquals("do_nothing", action.getIfMovedFileExists());
+    assertEquals("moved-dt-format", action.getMovedDateTimeFormat());
+
+    assertEquals(2, action.getFilesToMove().size());
+    ActionMoveFiles.FileToMove f = action.getFilesToMove().getFirst();
+    assertEquals("sourceFolder1", f.getSourceFileFolder());
+    assertEquals("destinationFolder1", f.getDestinationFileFolder());
+    assertEquals("wildcard1", f.getWildcard());
+    f = action.getFilesToMove().getLast();
+    assertEquals("sourceFolder2", f.getSourceFileFolder());
+    assertEquals("destinationFolder2", f.getDestinationFileFolder());
+    assertEquals("wildcard2", f.getWildcard());
+  }
+}
diff --git 
a/plugins/actions/movefiles/src/test/java/org/apache/hop/workflow/actions/movefiles/AzureMoveFilesIT.java
 
b/plugins/actions/movefiles/src/test/java/org/apache/hop/workflow/actions/movefiles/AzureMoveFilesIT.java
index 544748503f..94ec717f0e 100644
--- 
a/plugins/actions/movefiles/src/test/java/org/apache/hop/workflow/actions/movefiles/AzureMoveFilesIT.java
+++ 
b/plugins/actions/movefiles/src/test/java/org/apache/hop/workflow/actions/movefiles/AzureMoveFilesIT.java
@@ -100,8 +100,7 @@ class AzureMoveFilesIT {
   }
 
   @BeforeEach
-  void setup()
-      throws URISyntaxException, InvalidKeyException, StorageException, 
IOException, HopException {
+  void setup() throws URISyntaxException, InvalidKeyException, 
StorageException, IOException {
     // Retrieve storage account from connection-string.
     final BlobContainerClient container = 
blobServiceClient.getBlobContainerClient(CONTAINER_NAME);
     deleteFiles(CONTAINER_NAME);
@@ -131,8 +130,11 @@ class AzureMoveFilesIT {
     ActionMoveFiles action = defaultAction();
 
     String fileToRename = getFilePath("artists.csv");
-    action.sourceFileFolder[0] = fileToRename;
-    action.destinationFileFolder[0] = fileToRename + "done";
+
+    ActionMoveFiles.FileToMove fileToMove = new ActionMoveFiles.FileToMove();
+    fileToMove.setSourceFileFolder(fileToRename);
+    fileToMove.setDestinationFileFolder(fileToRename + "done");
+    action.getFilesToMove().add(fileToMove);
 
     action.execute(new Result(), 1);
 
@@ -147,8 +149,10 @@ class AzureMoveFilesIT {
     ActionMoveFiles action = defaultAction();
     IWorkflowEngine<WorkflowMeta> parentWorkflow = new LocalWorkflowEngine();
 
-    action.sourceFileFolder[0] = getFilePath("artists2.csv");
-    action.destinationFileFolder[0] = getFilePath("alreadythere.csv");
+    ActionMoveFiles.FileToMove fileToMove = new ActionMoveFiles.FileToMove();
+    fileToMove.setSourceFileFolder("artists2.csv");
+    fileToMove.setDestinationFileFolder("alreadythere.csv");
+    action.getFilesToMove().add(fileToMove);
 
     action.execute(new Result(), 1);
 
@@ -165,8 +169,11 @@ class AzureMoveFilesIT {
     ActionMoveFiles action = defaultAction();
     IWorkflowEngine<WorkflowMeta> parentWorkflow = new LocalWorkflowEngine();
 
-    action.sourceFileFolder[0] = getFilePath("artists2.csv");
-    action.destinationFileFolder[0] = getFilePath("alreadythere.csv");
+    ActionMoveFiles.FileToMove fileToMove = new ActionMoveFiles.FileToMove();
+    fileToMove.setSourceFileFolder(getFilePath("artists2.csv"));
+    fileToMove.setDestinationFileFolder(getFilePath("alreadythere.csv"));
+    action.getFilesToMove().add(fileToMove);
+
     action.setIfFileExists("do_nothing");
     action.execute(new Result(), 1);
 
@@ -181,8 +188,12 @@ class AzureMoveFilesIT {
     this.basePath = basePath;
 
     ActionMoveFiles action = defaultAction();
-    action.sourceFileFolder[0] = getFilePath("artists3.csv");
-    action.destinationFileFolder[0] = getFilePath("canbeoverwritten.csv");
+
+    ActionMoveFiles.FileToMove fileToMove = new ActionMoveFiles.FileToMove();
+    fileToMove.setSourceFileFolder(getFilePath("artists3.csv"));
+    fileToMove.setDestinationFileFolder(getFilePath("canbeoverwritten.csv"));
+    action.getFilesToMove().add(fileToMove);
+
     action.setIfFileExists("overwrite_file");
 
     action.execute(new Result(), 1);
@@ -197,8 +208,12 @@ class AzureMoveFilesIT {
       throws HopException {
     this.basePath = basePath;
     ActionMoveFiles action = defaultAction();
-    action.sourceFileFolder[0] = getFilePath("artists3.csv");
-    action.destinationFileFolder[0] = getFolderPath();
+
+    ActionMoveFiles.FileToMove fileToMove = new ActionMoveFiles.FileToMove();
+    fileToMove.setSourceFileFolder(getFilePath("artists3.csv"));
+    fileToMove.setDestinationFileFolder(getFolderPath());
+    action.getFilesToMove().add(fileToMove);
+
     action.setDestinationIsAFile(false);
 
     action.execute(new Result(), 1);
@@ -213,8 +228,12 @@ class AzureMoveFilesIT {
       throws HopException {
     this.basePath = basePath;
     ActionMoveFiles action = defaultAction();
-    action.sourceFileFolder[0] = getFilePath("artists3.csv");
-    action.destinationFileFolder[0] = getFilePath("fakecontainer", 
"artists-do-not-create-folder");
+
+    ActionMoveFiles.FileToMove fileToMove = new ActionMoveFiles.FileToMove();
+    fileToMove.setSourceFileFolder(getFilePath("artists3.csv"));
+    fileToMove.setDestinationFileFolder(
+        getFilePath("fakecontainer", "artists-do-not-create-folder"));
+    action.getFilesToMove().add(fileToMove);
     action.setCreateDestinationFolder(false);
 
     action.execute(new Result(), 1);
@@ -228,10 +247,14 @@ class AzureMoveFilesIT {
   void whenUseWildCards_thenMoveFiles(String basePath) throws HopException {
     this.basePath = basePath;
     ActionMoveFiles action = defaultAction();
-    action.sourceFileFolder[0] = getFolderPath(CONTAINER_NAME);
-    action.destinationFileFolder[0] = getFolderPath(ANOTHER_CONTAINER_NAME);
-    action.wildcard[0] = ".*wildcard.*.csv";
-    action.destinationIsAFile = false;
+
+    ActionMoveFiles.FileToMove fileToMove = new ActionMoveFiles.FileToMove();
+    fileToMove.setSourceFileFolder(getFolderPath(CONTAINER_NAME));
+    fileToMove.setDestinationFileFolder(getFolderPath(ANOTHER_CONTAINER_NAME));
+    fileToMove.setWildcard(".*wildcard.*.csv");
+    action.getFilesToMove().add(fileToMove);
+
+    action.setDestinationIsAFile(false);
     action.execute(new Result(), 1);
 
     assertThatFileExists(ANOTHER_CONTAINER_NAME, "artists-wildcard1.csv");
@@ -246,20 +269,18 @@ class AzureMoveFilesIT {
     // azuriteContainer.stop();
   }
 
-  private void deleteFiles(String containerName)
-      throws URISyntaxException, InvalidKeyException, StorageException {
+  private void deleteFiles(String containerName) {
     final BlobContainerClient container = 
blobServiceClient.getBlobContainerClient(containerName);
     container.listBlobs().forEach(blob -> 
container.getBlobClient(blob.getName()).deleteIfExists());
   }
 
   @AfterEach
-  void tearDown() throws Exception {
+  void tearDown() {
     // Clean up the Hop environment
     HopEnvironment.shutdown();
   }
 
-  private void uploadFileIntoContainer(String containerName, String... 
fileNames)
-      throws URISyntaxException, StorageException, IOException {
+  private void uploadFileIntoContainer(String containerName, String... 
fileNames) {
 
     for (String fileName : fileNames) {
       BlobServiceClient blobServiceClient =
diff --git 
a/plugins/actions/movefiles/src/test/java/org/apache/hop/workflow/actions/movefiles/MoveFilesActionHelper.java
 
b/plugins/actions/movefiles/src/test/java/org/apache/hop/workflow/actions/movefiles/MoveFilesActionHelper.java
index e6e2383ab3..0e9b4ff683 100644
--- 
a/plugins/actions/movefiles/src/test/java/org/apache/hop/workflow/actions/movefiles/MoveFilesActionHelper.java
+++ 
b/plugins/actions/movefiles/src/test/java/org/apache/hop/workflow/actions/movefiles/MoveFilesActionHelper.java
@@ -37,7 +37,6 @@ public class MoveFilesActionHelper {
     action.setMoveEmptyFolders(false);
     action.setSimulate(false);
     action.setArgFromPrevious(false);
-    action.allocate(1);
     action.setDestinationIsAFile(true);
     return action;
   }
diff --git 
a/plugins/actions/movefiles/src/test/java/org/apache/hop/workflow/actions/movefiles/WorkflowActionMoveFilesLocalTest.java
 
b/plugins/actions/movefiles/src/test/java/org/apache/hop/workflow/actions/movefiles/WorkflowActionMoveFilesLocalTest.java
index 4282ac80d5..a8a7c326e0 100644
--- 
a/plugins/actions/movefiles/src/test/java/org/apache/hop/workflow/actions/movefiles/WorkflowActionMoveFilesLocalTest.java
+++ 
b/plugins/actions/movefiles/src/test/java/org/apache/hop/workflow/actions/movefiles/WorkflowActionMoveFilesLocalTest.java
@@ -49,30 +49,40 @@ class WorkflowActionMoveFilesLocalTest {
   }
 
   @BeforeEach
-  void setUp() throws IOException {
+  void setUp() throws HopException {
     action = MoveFilesActionHelper.defaultAction();
     sourceFolder = testFolder.resolve("source").toFile();
-    sourceFolder.mkdirs();
+    boolean created = sourceFolder.mkdirs();
+    if (!created) {
+      throw new HopException(
+          "Folder " + sourceFolder + " was not created, or could not be 
created.");
+    }
     destinationFolder = testFolder.resolve("destination").toFile();
-    destinationFolder.mkdirs();
+    created = destinationFolder.mkdirs();
+    if (!created) {
+      throw new HopException(
+          "Folder " + destinationFolder + " was not created, or could not be 
created.");
+    }
   }
 
   @Test
   void testBasicFileMoveOperation() throws IOException, HopException {
     Path sourceFile = createTestFilePath(sourceFolder, "test.txt");
-    Path destFile = destinationFolder.toPath().resolve("test.txt");
+    Path destinationFile = destinationFolder.toPath().resolve("test.txt");
 
-    action.sourceFileFolder = new String[] {sourceFile.toString()};
-    action.destinationFileFolder = new String[] {destFile.toString()};
+    ActionMoveFiles.FileToMove fileToMove = new ActionMoveFiles.FileToMove();
+    fileToMove.setSourceFileFolder(sourceFile.toString());
+    fileToMove.setDestinationFileFolder(destinationFile.toString());
+    action.getFilesToMove().add(fileToMove);
     action.setDestinationIsAFile(true);
 
     Result result = action.execute(new Result(), 0);
     assertTrue(result.isResult(), "Move operation should succeed");
     assertFalse(Files.exists(sourceFile), "Source file should not exist");
-    assertTrue(Files.exists(destFile), "Destination file should exist");
+    assertTrue(Files.exists(destinationFile), "Destination file should exist");
     assertEquals(
         TEST_FILE_CONTENT,
-        Files.readString(destFile, StandardCharsets.UTF_8),
+        Files.readString(destinationFile, StandardCharsets.UTF_8),
         "File content should match");
   }
 
@@ -82,9 +92,11 @@ class WorkflowActionMoveFilesLocalTest {
     createTestFilePath(sourceFolder, "test2.txt");
     createTestFilePath(sourceFolder, "other.txt");
 
-    action.sourceFileFolder = new String[] {sourceFolder.getAbsolutePath()};
-    action.destinationFileFolder = new String[] 
{destinationFolder.getAbsolutePath()};
-    action.wildcard = new String[] {"test.*\\.txt"};
+    ActionMoveFiles.FileToMove fileToMove = new ActionMoveFiles.FileToMove();
+    fileToMove.setSourceFileFolder(sourceFolder.getAbsolutePath());
+    fileToMove.setDestinationFileFolder(destinationFolder.getAbsolutePath());
+    fileToMove.setWildcard("test.*\\.txt");
+    action.getFilesToMove().add(fileToMove);
     action.setDestinationIsAFile(false);
 
     Result result = action.execute(new Result(), 0);
@@ -99,12 +111,14 @@ class WorkflowActionMoveFilesLocalTest {
   @Test
   void testMoveToExistingFile() throws IOException, HopException {
     Path sourceFile = createTestFilePath(sourceFolder, "test.txt");
-    Path destFile = destinationFolder.toPath().resolve("test.txt");
+    Path destinationFile = destinationFolder.toPath().resolve("test.txt");
     String originalContent = "original content";
-    Files.writeString(destFile, originalContent, StandardCharsets.UTF_8);
+    Files.writeString(destinationFile, originalContent, 
StandardCharsets.UTF_8);
 
-    action.sourceFileFolder = new String[] {sourceFile.toString()};
-    action.destinationFileFolder = new String[] {destFile.toString()};
+    ActionMoveFiles.FileToMove fileToMove = new ActionMoveFiles.FileToMove();
+    fileToMove.setSourceFileFolder(sourceFile.toString());
+    fileToMove.setDestinationFileFolder(destinationFile.toString());
+    action.getFilesToMove().add(fileToMove);
     action.setDestinationIsAFile(true);
     action.setIfFileExists("fail");
 
@@ -113,27 +127,29 @@ class WorkflowActionMoveFilesLocalTest {
     assertTrue(Files.exists(sourceFile), "Source file should still exist");
     assertEquals(
         originalContent,
-        Files.readString(destFile, StandardCharsets.UTF_8),
+        Files.readString(destinationFile, StandardCharsets.UTF_8),
         "Destination content should be unchanged");
   }
 
   @Test
   void testMoveWithOverwrite() throws IOException, HopException {
     Path sourceFile = createTestFilePath(sourceFolder, "test.txt");
-    Path destFile = createTestFilePath(destinationFolder, "test.txt");
+    Path destinationFile = createTestFilePath(destinationFolder, "test.txt");
 
-    action.sourceFileFolder = new String[] {sourceFile.toString()};
-    action.destinationFileFolder = new String[] {destFile.toString()};
+    ActionMoveFiles.FileToMove fileToMove = new ActionMoveFiles.FileToMove();
+    fileToMove.setSourceFileFolder(sourceFile.toString());
+    fileToMove.setDestinationFileFolder(destinationFile.toString());
+    action.getFilesToMove().add(fileToMove);
     action.setDestinationIsAFile(true);
     action.setIfFileExists("overwrite_file");
 
     Result result = action.execute(new Result(), 0);
     assertTrue(result.isResult(), "Move with overwrite should succeed");
     assertFalse(Files.exists(sourceFile), "Source file should not exist");
-    assertTrue(Files.exists(destFile), "Destination file should exist");
+    assertTrue(Files.exists(destinationFile), "Destination file should exist");
     assertEquals(
         TEST_FILE_CONTENT,
-        Files.readString(destFile, StandardCharsets.UTF_8),
+        Files.readString(destinationFile, StandardCharsets.UTF_8),
         "File content should match source");
   }
 
@@ -142,36 +158,40 @@ class WorkflowActionMoveFilesLocalTest {
     Files.deleteIfExists(destinationFolder.toPath());
 
     Path sourceFile = createTestFilePath(sourceFolder, "test.txt");
-    Path destFile = destinationFolder.toPath().resolve("test.txt");
+    Path destinationFile = destinationFolder.toPath().resolve("test.txt");
 
-    action.sourceFileFolder = new String[] {sourceFile.toString()};
-    action.destinationFileFolder = new String[] {destFile.toString()};
+    ActionMoveFiles.FileToMove fileToMove = new ActionMoveFiles.FileToMove();
+    fileToMove.setSourceFileFolder(sourceFile.toString());
+    fileToMove.setDestinationFileFolder(destinationFile.toString());
+    action.getFilesToMove().add(fileToMove);
     action.setDestinationIsAFile(true);
     action.setCreateDestinationFolder(true);
 
     Result result = action.execute(new Result(), 0);
     assertTrue(result.isResult(), "Move should succeed");
     assertTrue(Files.exists(destinationFolder.toPath()), "Destination folder 
should be created");
-    assertTrue(Files.exists(destFile), "File should be moved");
+    assertTrue(Files.exists(destinationFile), "File should be moved");
   }
 
   @Test
   void testMoveWithOverwriteFileExist() throws IOException, HopException {
     Path sourceFile = createTestFilePath(sourceFolder, "test.txt");
-    Path destFile = createTestFilePath(destinationFolder, "test.txt");
+    Path destinationFile = createTestFilePath(destinationFolder, "test.txt");
 
-    action.sourceFileFolder = new String[] {sourceFile.toString()};
-    action.destinationFileFolder = new String[] {destinationFolder.toString()};
+    ActionMoveFiles.FileToMove fileToMove = new ActionMoveFiles.FileToMove();
+    fileToMove.setSourceFileFolder(sourceFile.toString());
+    fileToMove.setDestinationFileFolder(destinationFile.toString());
+    action.getFilesToMove().add(fileToMove);
     action.setDestinationIsAFile(true);
     action.setIfFileExists("overwrite_file");
 
     Result result = action.execute(new Result(), 0);
-    assertTrue(result.getResult(), "Move with overwrite should succeed");
+    assertTrue(result.isResult(), "Move with overwrite should succeed");
     assertFalse(Files.exists(sourceFile), "Source file should not exist");
-    assertTrue(Files.exists(destFile), "Destination file should exist");
+    assertTrue(Files.exists(destinationFile), "Destination file should exist");
     assertEquals(
         TEST_FILE_CONTENT,
-        Files.readString(destFile, StandardCharsets.UTF_8),
+        Files.readString(destinationFile, StandardCharsets.UTF_8),
         "File content should match source");
   }
 
diff --git 
a/plugins/actions/movefiles/src/test/java/org/apache/hop/workflow/actions/movefiles/WorkflowActionMoveFilesTest.java
 
b/plugins/actions/movefiles/src/test/java/org/apache/hop/workflow/actions/movefiles/WorkflowActionMoveFilesTest.java
deleted file mode 100644
index f15dd2aad3..0000000000
--- 
a/plugins/actions/movefiles/src/test/java/org/apache/hop/workflow/actions/movefiles/WorkflowActionMoveFilesTest.java
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.hop.workflow.actions.movefiles;
-
-import java.util.Arrays;
-import java.util.List;
-import java.util.Map;
-import org.apache.hop.junit.rules.RestoreHopEngineEnvironmentExtension;
-import 
org.apache.hop.workflow.action.loadsave.WorkflowActionLoadSaveTestSupport;
-import org.junit.jupiter.api.extension.RegisterExtension;
-
-class WorkflowActionMoveFilesTest extends 
WorkflowActionLoadSaveTestSupport<ActionMoveFiles> {
-  @RegisterExtension
-  static RestoreHopEngineEnvironmentExtension env = new 
RestoreHopEngineEnvironmentExtension();
-
-  @Override
-  protected Class<ActionMoveFiles> getActionClass() {
-    return ActionMoveFiles.class;
-  }
-
-  @Override
-  protected List<String> listAttributes() {
-    return Arrays.asList(
-        "addDate",
-        "addTime",
-        "specifyFormat",
-        "dateTimeFormat",
-        "addDateBeforeExtension",
-        "doNotKeepFolderStructure",
-        "ifFileExists",
-        "destinationFolder",
-        "ifMovedFileExists",
-        "movedDateTimeFormat",
-        "addMovedDateBeforeExtension",
-        "addMovedDate",
-        "addMovedTime",
-        "specifyMoveFormat",
-        "createMoveToFolder",
-        "simulate");
-  }
-
-  @Override
-  protected Map<String, String> createGettersMap() {
-    return toMap(
-        "add_date", "isAddDate",
-        "add_time", "isAddTime",
-        "SpecifyFormat", "isSpecifyFormat",
-        "date_time_format", "getDateTimeFormat",
-        "AddDateBeforeExtension", "isAddDateBeforeExtension",
-        "DoNotKeepFolderStructure", "isDoNotKeepFolderStructure",
-        "iffileexists", "getIfFileExists",
-        "destinationFolder", "getDestinationFolder",
-        "ifmovedfileexists", "getIfMovedFileExists",
-        "moved_date_time_format", "getMovedDateTimeFormat",
-        "AddMovedDateBeforeExtension", "isAddMovedDateBeforeExtension",
-        "add_moved_date", "isAddMovedDate",
-        "add_moved_time", "isAddMovedTime",
-        "SpecifyMoveFormat", "isSpecifyMoveFormat");
-  }
-
-  @Override
-  protected Map<String, String> createSettersMap() {
-    return toMap(
-        "add_date", "setAddDate",
-        "add_time", "setAddTime",
-        "SpecifyFormat", "setSpecifyFormat",
-        "date_time_format", "setDateTimeFormat",
-        "AddDateBeforeExtension", "setAddDateBeforeExtension",
-        "DoNotKeepFolderStructure", "setDoNotKeepFolderStructure",
-        "iffileexists", "setIfFileExists",
-        "destinationFolder", "setDestinationFolder",
-        "ifmovedfileexists", "setIfMovedFileExists",
-        "moved_date_time_format", "setMovedDateTimeFormat",
-        "AddMovedDateBeforeExtension", "setAddMovedDateBeforeExtension",
-        "add_moved_date", "setAddMovedDate",
-        "add_moved_time", "setAddMovedTime",
-        "SpecifyMoveFormat", "setSpecifyMoveFormat",
-        "simulate", "setSimulate");
-  }
-}
diff --git a/plugins/actions/movefiles/src/test/resources/action-move-files.xml 
b/plugins/actions/movefiles/src/test/resources/action-move-files.xml
new file mode 100644
index 0000000000..9f4cf3dc50
--- /dev/null
+++ b/plugins/actions/movefiles/src/test/resources/action-move-files.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~       http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<action>
+    <move_empty_folders>Y</move_empty_folders>
+    <arg_from_previous>Y</arg_from_previous>
+    <include_subfolders>Y</include_subfolders>
+    <add_result_filesname>Y</add_result_filesname>
+    <destination_is_a_file>Y</destination_is_a_file>
+    <create_destination_folder>Y</create_destination_folder>
+    <add_date>Y</add_date>
+    <add_time>Y</add_time>
+    <SpecifyFormat>Y</SpecifyFormat>
+    <date_time_format>dt-format</date_time_format>
+    <nr_errors_less_than>10</nr_errors_less_than>
+    <success_condition>success_if_no_errors</success_condition>
+    <AddDateBeforeExtension>Y</AddDateBeforeExtension>
+    <DoNotKeepFolderStructure>Y</DoNotKeepFolderStructure>
+    <iffileexists>overwrite_file</iffileexists>
+    <destinationFolder>destination-folder</destinationFolder>
+    <ifmovedfileexists>do_nothing</ifmovedfileexists>
+    <moved_date_time_format>moved-dt-format</moved_date_time_format>
+    <create_move_to_folder>Y</create_move_to_folder>
+    <add_moved_date>Y</add_moved_date>
+    <add_moved_time>Y</add_moved_time>
+    <SpecifyMoveFormat>Y</SpecifyMoveFormat>
+    <AddMovedDateBeforeExtension>Y</AddMovedDateBeforeExtension>
+    <simulate>Y</simulate>
+    <fields>
+        <field>
+            <source_filefolder>sourceFolder1</source_filefolder>
+            <destination_filefolder>destinationFolder1</destination_filefolder>
+            <wildcard>wildcard1</wildcard>
+        </field>
+        <field>
+            <source_filefolder>sourceFolder2</source_filefolder>
+            <destination_filefolder>destinationFolder2</destination_filefolder>
+            <wildcard>wildcard2</wildcard>
+        </field>
+    </fields>
+</action>


Reply via email to