Every example I’ve read for moving files uses the File System Task and a collection of files in a single folder. It’s a super easy move and pretty much all you do is point the File System task at it and roll. But what happens if you have several files, inconsistently named, that have to go to different places? One way to do it would be to create a bunch of File System Tasks but there is a better way.
Lets set up our base file system as follows:
Note I named the files the way I did to simulate my old work environment (we exported data to our web and bi servers). You can name them whatever you like and the naming pattern I use (-web and -server) is just there to see if what I did worked.
Test Data Folder: C:\testData
Server Destination: C:\testData\server
Web Server: C:\testData\web
Now create 6 text (or whatever type you’d like) files in the C:\testData folder. Name them as follows:
What we’re going to do is use SSIS to read through these 6 files and then place copies of them in the appropriate sub-folder. We’re also not going to use the “web” or “server” part of the names as a crutch. Treat that part like it doesn’t exist. This is a several part process that is a bit confusing in some places but it does work and it is definitely better than 6 separate File System tasks.
Step 1: Create a table in a database that lists the source (where they are) and destination (where we want them) path information for the above files.
CREATE TABLE fileMoves ( id int NOT NULL IDENTITY(1,1) PRIMARY KEY, name VARCHAR(50), source VARCHAR(255), destination VARCHAR(255) );
Next we populate the table with the relevant information for the files we created earlier.
INSERT INTO fileMoves(name, source, destination) VALUES ('accounting-server','c:\testData\accounting-server.txt','c:\testData\server'), ('credit-server','c:\testData\credit-server.txt','c:\testData\server'), ('sales-server','c:\testData\sales-server.txt','c:\testData\server'), ('accounting-web','c:\testData\accounting-web.txt','c:\testData\web'), ('credit-web','c:\testData\credit-web.txt','c:\testData\web'), ('sales-web','c:\testData\sales-web.txt','c:\testData\web'); SELECT * FROM fileMoves; id name source destination 1 accounting-server c:\testData\accounting-server.txt c:\testData\server 2 credit-server c:\testData\credit-server.txt c:\testData\server 3 sales-server c:\testData\sales-server.txt c:\testData\server 4 accounting-web c:\testData\accounting-web.txt c:\testData\web 5 credit-web c:\testData\credit-web.txt c:\testData\web 6 sales-web c:\testData\sales-web.txt c:\testData\web
Step 2: Create an Execute SQL Task, process it as a result set and place the result set into an object type variable.
I have to admit that this threw me for a loop at first. It was not how I expected things to work. Anyways, here come a bunch of configuration steps.
In the General tab.
- Drag an Execute SQL task to the control flow. You can rename it, or not, at your discretion.
- Open the result set.
- Set the ResultSet property to “full Result Set”.
- Set ConnectionType to “OLE DB”.
- In Connection, click “New Connection” and point the connection to the database that you created the fileMoves table in.
- In SQLSourceType select “Direct Input”.
- In SQLStatement type “SELECT name, source, destination FROM fileMoves”.
In the “Result Set” tab.
- Click Add.
- In the “Variable Name” column select “New Variable”. Use the following properties.
- Name: varMoveFileSet.
- Value Type: Object.
- You can leave the rest in their defaults.
- In the “Result Name” column set the value to 0. If this were a single row result set these would be the ordinal positions but since we’re plowing the the entire result set into the variable we use 0.
Click OK to close this task.
You now have a working Execute SQL task that has passed it’s results into an object type variable with the name of varMoveFileSet.
Step 3: Set up a Foreach Loop Container to loop through the result set.
Now we need to process the result set. In order to do that we need to use an ADO Enumerator in the Foreach container. Yeah, I bet you saw that one coming. Here is how you do that.
- Drag a Foreach Loop Container to the control flow and connect the Execute SQL task to it.
- Double-click the container to open it.
In the collection tab do the following:
- Change the Enumerator value to “Foreach ADO Enumerator”.
- Change the “ADO object source variable” to the variable we created earlier “User::varFileMoveSet”.
- Set Enumeration Mode to “Rows in the first table”.
You have now connected the container to the table results you generated earlier but you still need to map them to variables so SSIS can process them.
Click on variable mappings, then in the variable column create 3 new variables and name them as follows:
Index them as index 0, 1 and 2 in the order they are listed above.
Click OK to close the Foreach Loop container.
Step 4: Add a File System task and configure it to use the information in the prior steps.
This is actually the easiest part of the whole process. Just do the following:
- Drag a File System task into the Foreach Loop container and rename it, or not.
- Double-click the container to open it.
- Set IsDestinationPathVariable to True.
- Set DestinationVariable to “User::myDestination”.
- Set OverwriteDestination to True.
- Set Operation to Copy.
- Set IsSourcePathVariable to True.
- Set SourceVariable to “User::mySource”
Click OK to close the File System Task. At this point you are almost done. In fact, you might expect to have a working package. There’s just one small detail, a validation error.
Step 5: Fix the validation error.
Right now you likely have a package with an X in the File System task. The reason for this is that the package can’t validate the variables. The way you fix this is by setting the DelayValidation property to true.
- Click on the File System Task and click F4 to open the property window.
- Find the DelayValidation property and set it to True.
The red X should be gone and you can run the package. If you did everything right, or probably more importantly, I wrote it right, you should have the -server files in the server folder, and the -web files in the web folder.
There are other ways to do this and for small groups of files maybe it wouldn’t even be worth it to use SSIS. I know in the AIX / Linux world I used to inhabit we just used RSYNC, put the commands in a file, and let the crontab run them. But, if you had a lot of files moving, or you wanted someone to maintain a file list without getting on the server, this could be a good solution.