I'm using a Script Task (C#) within SSIS to move all .txt files from one folder to another. However, when I execute this, nothing happens. The Script Task actually reports success but the text files do not move. I'm using variables for all the paths - they all start with 2 backslashes and end with 1 back slash.
All I want to do is move all text files from the source destination to the destination folder.
What am I missing?
public void Main()
{
DirectoryInfo di = new DirectoryInfo(Dts.Variables["IN_Folder"].Value.ToString());
string destinationFolder = Dts.Variables["User::IN_Folder_Processing"].Value.ToString();
string sourceFolder = Dts.Variables["User::IN_Folder"].Value.ToString();
FileInfo[] fi = di.GetFiles("*.txt");
String filename = fi[0].Name;
string sourceFileName = filename;
string destinationFile = destinationFolder + sourceFileName;
string sourceFile =sourceFolder + sourceFileName;
if (File.Exists(destinationFile))
File.Delete(destinationFile);
// To move a file or folder to a new location:
System.IO.File.Move(sourceFile, destinationFile);
Dts.TaskResult = (int)ScriptResults.Success;
}
Like I mentioned in the comments, there seems to be no need to use a Script Task to do this; a far better option would be a Foreach Loop Container and a FileSystem Task.
Firstly create the Foreach Loop Container, open the editor and go to the Collection Pane. Change Enumerator to Foreach File Enumerator. I assume you are using a variable for the directory, so click ... for Expressions and select Directory for the Property and your variable for the expression.
As you specifically want to deal with txt files, change Files to *.txt. What option you use for Retreive File Name depends on how your determining the destination. I'm going to assume you have another variable with the directory target, so select Name and extention.
Go to the Variable Mappings pane and select your filename variable, or create a new one. Leave the Index as 0. This will store the Name and extension of the file you are going to move.
Create a new variable in your package, called OriginalFilePath, or something easily identifiable. Set the value to string and then change the Scope to your Foreach Loop Container. Now open the expression pane for the variable and set the expression to something like:
#[User::SourceDirectoryVariable] + "\\" + #[User::FileNameVariable]
Obviously change the variable names to what they need to be. Now create a second variable (same settings), however, using your destination directory variable instead of the source (#[User::DestinationDirectoryVariable] + "\\" + #[User::FileNameVariable]).
Now, in your Control Flow, create a File System Task within your Foreach Loop Container. Change Operation to Move File. Then fill in the rest of the pane as needed (IsSourceVariable will be True, and then select your variable). Do the same for the destination, and then you should be good to go.
Any problems, please do comment with the error.
You should avoid manually concatenating file paths using the string + operator. This leaves a lot of room for error. Use System.IO.Path.Combine(). This ensures all leading and trialing slashes are formatted properly.
There's also no need to rebuild the file paths manually using all those additional variables. Something like this will work just fine so long as your input variable directories are correct:
public void Main()
{
DirectoryInfo di = new DirectoryInfo(Dts.Variables["IN_Folder"].Value.ToString());
string destinationFolder = Dts.Variables["User::IN_Folder_Processing"].Value.ToString();
FileInfo[] fi = di.GetFiles("*.txt");
foreach (FileInfo f in fi)
{
FileInfo destinationFile = new FileInfo(Path.Combine(destinationFolder, f.Name));
if (destinationFile.Exists)
destinationFile.Delete();
f.MoveTo(destinationFile.FullName);
}
Dts.TaskResult = (int)ScriptResults.Success;
}
Related
I have this project where I'm iterating recursively in some folders and copy them to a new directory.
In the 2nd level of folders (child folder) I have a txt file which I am reading. Now, when I read that file, I parse a string and I want to give that string to the parent folder and assign it as its name. So far I can only do for its File only, because there is accessible but when I try to do it for the parent folder, it doesn't recognize the variable (which of course, makes sense!)
EDIT: I commented the code so it will be a little bit clearer.
Now, Is there any way I can achieve this?
Here's my code:
static void CopyDirectory(string sourceDir, string destinationDir, bool recursive)
{
//accessing the directiories inse of Destionationed directory
DirectoryInfo[] dirs = dir.GetDirectories();
Directory.CreateDirectory(destinationDir);
if (recursive)
{
// reading every folder inside first parent folder
foreach (DirectoryInfo subDir in dirs)
{
//reading every folder inside the second folder
DirectoryInfo[] Subdirs = subDir.GetDirectories();
foreach (DirectoryInfo subDir2 in Subdirs)
{
//setting the new path where I want my new files to be stored.
string newDestinationDir = Path.Combine(destinationDir, subDir2.Name);
//Now, here its where I want to change the main folder's name, but the value must be taking from inside it's file.
CopyDirectory(subDir2.FullName, newDestinationDir, true);
FileInfo[] SubDirsFiles = subDir2.GetFiles();
foreach (FileInfo getFile in SubDirsFiles)
{
File.Copy(getFile.FullName, newDestinationFile + "_" + dictionary["XECM_DOC_TYPE"], true);
}
}
}
}
}
Note: I'm using Dictiony to story the data I read from file, and thats what I'm trying to pass to the parent folder, exclusively-to the CopyDirectory(subDir2.FullnName,NewDestinationDir+dictionary["XECM_DOC_TYPE"],true) but logically it can't recognize the dictionary part because it is declared and initialized inside the FileInfo part...
I hope I was clear enough.
I have a C# console application that sends Excel spreadsheet attachments through email.
I have given the file path in App.config. While trying to find the file, the code looks at proper location. But when trying to attach the file inside the foreach statement, it is looking in code's bin folder.
What am I doing wrong here?
DirectoryInfo dir1 = new DirectoryInfo(ConfigurationManager.AppSettings.Get("FilePath"));
FileInfo[] folderFiles = null;
folderFiles = dir1.GetFiles();
foreach (FileInfo aFile in folderFiles)
{
message.Attachments.Add(new Attachment(aFile.Name));
}
You need to use aFile.FullName (includes the full path) rather than aFile.Name (only the filename). If a command is not doing what you expect, you should check the documentation.
Alternatively, you could make it simpler:
string dir1 = ConfigurationManager.AppSettings.Get("FilePath");
foreach(string aFile in Directory.EnumerateFiles(dir1))
{
message.Attachments.Add(new Attachment(aFile));
}
as Directory.EnumerateFiles simply returns the full filenames and you would have to think about not doing so (e.g. by using Path.GetFileName) to do otherwise.
I am trying to create a folder with a variable that can change, I am using
System.IO.Directory.CreateDirectory
When I hardcode a value like so:
var folder = #"C:\Users\Laptop\Documents\bot\random string here"
It creates that directory, but when I pass data to my method and try and use it like so:
var folder = #"C:\Users\Laptop\Documents\bot\" +
articlename.Replace(" ", "_");
System.IO.Directory.CreateDirectory(folder);
It doesn't create it nor break. How can I use the variable to create a folder like that?
My article is a random string like "hello this is a article yadda"
I solved by adding my paths together correctly as below
string path = root +"/"+ newfolder;
if (!Directory.Exists(path))
{
Directory.CreateDirectory(path);
// To move a file or folder to a new location:
//System.IO.File.Move(fi.FullName, path);
}
I have a list of directories - these folders are all websites - and I need to write some code to traverse down each one of these directories until I find the index.html file. When I find index.html, I need to write the entire path out to a text file. I know how to do basic file I/O, such as writing data to a file, but what I'm getting hung up on is how to traverse down each directory until I hit a certain file, then capture that entire path, then continue on to the next folder/directory. I'm not sure where to start and I was hoping I could find some guidance from you all.
There is a function that can do that : Directory.GetFiles Method (String, String, SearchOption)
Returns the names of files (including their paths) that match the specified search pattern in the specified directory, using a value to determine whether to search subdirectories.
If you just want to find the very first instance of a file with a particular name and stop searching immediately when you find it, this is the most efficient approach.
It uses the SearchOption.AllDirectories option to tell it to recursively descend the directories for you.
string rootPath = "X:\\MyRoot";
string targetPattern = "index.html";
string fullPath = Directory
.EnumerateFiles(rootPath, targetPattern, SearchOption.AllDirectories)
.FirstOrDefault();
if (fullPath != null)
Console.WriteLine("Found " + fullPath);
else
Console.WriteLine("Not found");
(Note that if you use Directory.GetFiles() it will iterate over all possible folders, even if it has already found an instance of the target file, whereas EnumerateFiles() allows you to stop iterating as soon as the file is found.)
This uses Linq's FirstOrDefault() to stop iterating as soon as a file is found, so you'll have to add using System.Linq;
Note that FirstOrDefault() will return null (for strings, as in this example) when there are no items in the sequence.
One important thing to be aware of is that both Directory.EnumerateFiles() and Directory.GetFiles() will throw exceptions if you attempt to access directories that you aren't allowed to (for example, if you start at the root of C:\, it could attempt to access C:\$Recycle.Bin which will cause an exception).
If you have many directories and files may enumerate them; it could be convenient if you want to exclude some directories:
public static String FindFileDeep(String path, String fileName) {
foreach(String file in Directory.EnumerateFiles(path))
if (String.Equals(Path.GetFileName(file), fileName, StringComparison.OrdinalIgnoreCase))
return file;
foreach (var dir in Directory.EnumerateDirectories(path)) {
// You can exclude some directories here:
// if (...) continue;
String result = FindIndexHtml(dir);
if (!String.IsNullOrEmpty(result))
return result;
}
return null;
}
...
String indexHtml = FindFileDeep(#"C:\MyFiles", "index.html");
Create a method that gets the contents of a directory (DirectoryInfo class) that is passed as a parameters.
Cycle through each of the .GetFiles() of the DirectoryInfo to find the flie.
Then, if need be, use the .GetDirectories() list and cycle through them re-calling the same function with the found directory name.
Disclaimer: Uncompiplied/untests - Prototype...
static void Main(string[] args)
{
FileInfo fi = FindFile("index.html", new DirectoryInfo("C:\\"));
}
static FileInfo FindFile(string Name, DirectoryInfo di)
{
FileInfo fiFound = null;
// Try and find it in this directory
FileInfo[] fiList = di.GetFiles("index.html");
if (fiList.Length == 0)
{
foreach (DirectoryInfo diCycle in di.GetDirectories())
{
fiFound = FindFile(Name, diCycle);
}
}
else
{
fiFound = fiList.First();
}
return (fiFound);
}
i want to create C# mass file renamer, here is my UI
i have created tes folder, inside of tes there's a file which is 1.txt.
i want to create my program to add prefix and suffix to the files, so 1.txt will become
prefix1suffix
but then i got an error
it's said file already exist though there's only one file on tes folder, which is 1.txt how do i make it work ? where's the error comes from ?
i have tried the following code
private void Rename(string prefix, string filepath, string suffix)
{
//i don't use prefix suffix yet to make sure if my function works
DirectoryInfo d = new DirectoryInfo(filepath);
FileInfo[] file = d.GetFiles();
try
{
foreach (FileInfo f in file )
{
File.Move(f.FullName,"stackoverflow");
}
}
catch (Exception e)
{
cmd.cetakGagal(e.ToString(), title);
}
cmd.cetakSukses("Rename Success", title);
}
and it returns same error as the second picture above.
the following picture is tes folder, there's nothing in tes folder except 1.txt
You are calling File.Move() with a full path for your sourceFileName and a relative path for your destFileName. The relative file path is relative to the current working directory and not to the source file path. I expect that a stackoverflow file exists in the current working directory, most likely created the first time you ran this code.
your File.Move is changing them all to StackOverflow not using the prefix and suffix. If you only have one file in the directory it shouldn't be an issue. Are you sure there is only 1 file?
public static void Move(
string sourceFileName,
string destFileName
)
Looking at this answer might be the clue as you are specifying relative path for the destination file. To obtain the current working directory, see GetCurrentDirectory
The sourceFileName and destFileName arguments are permitted to specify
relative or absolute path information. Relative path information is
interpreted as relative to the current working directory.
You should change
File.Move(f.FullName,"stackoverflow");
to
string fileName = f.Name.Replace(f.Extenstion,string.Empty);
string newFileName = string.Format("{0}{1}{2}",prefix,fileName,suffix);
string newFileWithPath = Path.Combine(f.Directory,newFileName);
if (!File.Exists(newFileWithPath))
{
File.Move(f.FullName,newFileWithPath);
}
The code above will give you that error since, after the first run through, "stackoverflow" exists as a file. Make sure that you check if the destination file exists (using File.Exists) before calling File.Move.
Since your goal is renaming, I would suggest using a test folder filled with files rather than using a piecemeal approach. See if something like this helps:
private void Rename(string prefix, string filepath, string suffix)
{
//i don't use prefix suffix yet to make sure if my function works
DirectoryInfo d = new DirectoryInfo(filepath);
FileInfo[] file = d.GetFiles();
try
{
foreach (FileInfo f in file )
{
f.MoveTo(#filepath + #"\" + prefix + f.Name.Insert(f.Name.LastIndexOf('.'),suffix));
}
}
catch (Exception e)
{
cmd.cetakGagal(e.ToString(), title);
}
cmd.cetakSukses("Rename Success", title);
}
on a side note using a listview to display the filenames and the changes before they're committed will help prevent unwanted changes.