I have an array of filepaths in a directory and I'm trying to move certain files based on alphabet.
string[] filePaths = Directory.GetFiles(#"C:\user\desktop\folder", "*.txt");
foreach (var file in filePaths)
{
if (file.StartsWith("A"))
{
//Move file
The obvious problem is that file.StartWith is pulling the entire filepath (C:\user\desktop\folder\Albert.txt) Which doesn't start with 'A'
So what would be the best way to just target the start of the actual file?
Thanks in advance.
I got it working with Path.GetFileName as per the suggestion by #Jimi
What about this code
var dir = new DirectoryInfo(#"C:\user\desktop\folder");
var files = dir.GetFiles();
foreach (var file in files)
{
if(file.Name.StartsWith("A"))
{
//Move file
You say you're looking to move files by alphabet- if you mean to put files into a folder whose name is the same as the first char of the filename then perhaps:
var desktop = Environment.GetFolderPath(Environment.SpecialFolder.Desktop); //don't hard code the path to the desktop
var root = Path.Combine(desktop, "foldernamehere"); //use path.combine to build paths
foreach(var f in directory.EnumerateFiles(root, "*.txt")){ //prefer EnumerateFiles over GetFiles
var filename = Path.GetFileName(f);
var dest = Path.Combine(root, filename.Remove(1));
Directory.CreateDirectory(dest); //safe to call even if exists, ensures exists
File.Move(f, Path.Combine(dest, filename));
}
See comments for more info
If you have a string that represents a full filename (or directory name), and you want the name without the directory, consider to use Path.GetFileName
string fullFileName = "C:\user\desktop\folder\Albert.txt";
string fileName = Path.GetDirectoryName(fullFileName);
fileName will be "Albert.txt"
With this in mind, your query will be easy:
IEnumerable<string> fullFileNames = ...
char startChar = 'A';
IEnumerable<string> fileNamesThatStartWithStartChar = fullFileNames
.Where(fileName => Path.GetDirectoryName(fileName).StartsWitch(startChar));
In words: from every fileName in the sequence of fullFileName, take the fileName without the directory information. Keep the fileName if this "fileName without directory information" starts with the startChar.
Note: StartsWitch(char) is case sensitive. If you want to check case insensitive, use String.StartsWitch(string, stringComparison)
There's room for improvement!
If you think that there might be a chance that you won't be using all information of all files, consider to use Directory.EnymerateFiles instead of GetFiles. This way, if at the end of your LINQ you decide to use only 3 of the fetched files (or worse: FirstOrDefault(), or Any()), you won't have fetched all files.
Related
Beginner coder here.
I need to add the GetLastWriteTime string to my filename using the (rename) file.move method. How do I add a string using file.move?
I've looked up some similar info, and I've gotten part of the answer I need. System.IO.File.Move("oldfilename", "newfilename"); is the code I'll need help with. I tried adding a string to the newfilename, but it only supports directory.
string[] files = Directory.GetFiles("C:/foto's", "*", SearchOption.TopDirectoryOnly);
string filename = Path.GetFileName(photo);
DateTime fileCreatedDate = System.IO.File.GetLastWriteTime(filename);
System.IO.File.Move(#"C:\foto's", #"C:\foto's" + fileCreatedDate);
Expected error, string cannot be accepted in a directory place.
I've always preferred to use FileInfo objects for stuff like this as they have the dates built in, have MoveTo rather than using the static File.Move etc ...
FileInfo[] fis = new DirectoryInfo(#"C:\foto's").GetFiles("*", SearchOption.TopDirectoryOnly);
foreach(FileInfo fi in fis){
//format a string representing the last write time, that is safe for filenames
string datePart = fi.LastWriteTimeUtc.ToString("_yyyy-MM-dd HH;mm;ss"); //use ; for time because : is not allowed in path
//break the name into parts based on the .
string[] nameParts = fi.Name.Split('.');
//add the date to the last-but-one part of the name
if(nameParts.Length == 1) //there is no extension on the file
nameParts[0] += datePart;
else
nameParts[nameParts.Length-1] += datePart;
//join the name back together
string newName = string.Join(".", nameParts);
//move the file to the same directory but with a new name. Use Path.Combine to join directory and new file name into a full path
fi.MoveTo(Path.Combine(fi.DirectoryName, newName));
}
Directory.Move(#"c:\foto's", #"c:\photos"); //fix two typos in your directory name ;)
I have a dropdown with list of file names. When a file name is selected in the dropdown I do the following
string filename = ddl.SelectedItem.Text;
string path = "F:\\WorkingCopy\\files\\" + filename +".docx";
DownloadFile(path,filename);
In the file folder files may contain any extension . Since i have hard coded ".docx" in string path everything works fine. But I need to get the extension of the file name with the ddl.SelectedItem.Text alone. Can you tell me how to do this?
Things I have
1.) File name without extension in
string filename = ddl.SelectedItem.Text;
2.) Path where the file is located
string path = "F:\\WorkingCopy\\files\\" + filename
I am trying to get the file extension with these . Can any one suggest on this?
You can use Directory.EnumerateFiles() like this:
string path = "F:\\WorkingCopy\\files\\";
string filename = ddl.SelectedItem.Text;
string existingFile = Directory.EnumerateFiles(path, filename + ".*").FirstOrDefault();
if (!string.IsNullOrEmpty(existingFile))
Console.WriteLine("Extension is: " + Path.GetExtension(existingFile));
Directory.EnumerateFiles searches the path for files like filename.*. Path.GetExtension() returns the extension of the found file.
In general, I prefer to use EnumerateFiles() instead of GetFiles because it returns an IEnumerable<string> instead string[]. This suggests that it only returns the matching files as needed instead searching all matching files at once. (This doesn't really matter in your case, just a general note).
Use the Directory.GetFiles() method. Something like this
string[] files = Directory.GetFiles("F:\\WorkingCopy\\files\\", filename+".*");
This should get you an array of filenames with the same filename but different extensions. If you have only one, then you can always use the first one.
You can use Directory.GetFiles Method:
string result = Directory.GetFiles(path, filename + ".*").FirstOrDefault();
see here
here " * " is the WildCard and will search for the Filename starts with YourFileName.
you can achieve that with followed by line
try
{
var extensions = new List<string>();
var files = Directory.GetFiles("F:\\WorkingCopy\\files\\", filename + ".*", System.IO.SearchOption.TopDirectoryOnly);
foreach (var tmpfile in files)
extensions.Add(Path.GetExtension(tmpfile));
}
catch (Exception ex)
{
throw ex;
}
will this help you?
You can simply split them by dot, For example, try this code
string folder = #"F:\\WorkingCopy\\files\\";
var files = System.IO.Directory.GetFiles(folder, filename + ".*");
if (files.Any())
{
string ext = System.IO.Path.GetExtension(files.First()).Substring(1);
}
This code gives me result that the extension for this is txt file.
I have a directory filled with multiple excel files that I would like to rename. The names all have leading integers and a '-'. For example: 0123456-Test_01. I would like to rename all of the files within this directory by removing this prefix. 0123456-Test_01 should just be Test_01. I can rename a hard coded instance of a string, but am having trouble getting the files and renaming all of them.
My code is below. Any help is appreciated, as I am clearly new to C#.
public static void Main()
{
//Successfully splits hardcoded string
var temp = "0005689-Test_01".Split('-');
Console.WriteLine(temp[1]);
Console.ReadLine();
//Unsuccessful renaming of all files within directory
List<string> files = System.IO.Directory.GetFiles(#"C:\Users\acars\Desktop\B", "*").ToList();
System.IO.File.Move(#"C:\Users\acars\Desktop\B\", #"C:\Users\acars\Desktop\B\".Split('-'));
foreach (string file in files)
{
var temp = files.Split('-');
return temp[1];
};
}
There are some errors to fix in your code.
The first one is the wrong usage of the variable files. This is the full list of files, not the single file that you want to split and move. As explained comments you should use the iterator result stored in the variable file
The most important problem is the fact that the File.Move method throws an exception if the destination file exists. After removing the first part of your filename string, you cannot be sure that the resulting name is unique in your directory.
So a check for the existance of the file before the Move is mandatory.
Finally, it is better use Directory.EnumerateFiles because this method allows you to start the execution of your moving code without loading first all filenames in memory in a list. (In a folder full of files this could make a noticeable difference in speed)
public static void Main()
{
string workPath = #"C:\Users\acars\Desktop\B";
foreach (string file in Directory.EnumerateFiles(workPath)
{
string[] temp = file.Split('-');
if(temp.Length > 1)
{
string newName = Path.Combine(workPath, temp[1]);
if(!File.Exists(newName))
File.Move(file, newName);
}
}
}
Pay also attention to the comment below from CodeNotFound. You are using an hard-coded path so the problem actually doesn't exist, but if the directory contains a single "-" in its name then you should use something like this to get the last element in the splitted array
string newName = Path.Combine(workPath, temp[temp.Length-1]);
I have a list of filename with full path which I need to remove the filename and part of the file path considering a filter list I have.
Path.GetDirectoryName(file)
Does part of the job but I was wondering if there is a simple way to filter the paths using .Net 2.0 to remove part of it.
For example:
if I have the path + filename equal toC:\my documents\my folder\my other folder\filename.exe and all I need is what is above my folder\ means I need to extract only my other folder from it.
UPDATE:
The filter list is a text box with folder names separated by a , so I just have partial names on it like the above example the filter here would be my folder
Current Solution based on Rob's code:
string relativeFolder = null;
string file = #"C:\foo\bar\magic\bar.txt";
string folder = Path.GetDirectoryName(file);
string[] paths = folder.Split(Path.DirectorySeparatorChar);
string[] filterArray = iFilter.Text.Split(',');
foreach (string filter in filterArray)
{
int startAfter = Array.IndexOf(paths, filter) + 1;
if (startAfter > 0)
{
relativeFolder = string.Join(Path.DirectorySeparatorChar.ToString(), paths, startAfter, paths.Length - startAfter);
break;
}
}
How about something like this:
private static string GetRightPartOfPath(string path, string startAfterPart)
{
// use the correct seperator for the environment
var pathParts = path.Split(Path.DirectorySeparatorChar);
// this assumes a case sensitive check. If you don't want this, you may want to loop through the pathParts looking
// for your "startAfterPath" with a StringComparison.OrdinalIgnoreCase check instead
int startAfter = Array.IndexOf(pathParts, startAfterPart);
if (startAfter == -1)
{
// path not found
return null;
}
// try and work out if last part was a directory - if not, drop the last part as we don't want the filename
var lastPartWasDirectory = pathParts[pathParts.Length - 1].EndsWith(Path.DirectorySeparatorChar.ToString());
return string.Join(
Path.DirectorySeparatorChar.ToString(),
pathParts, startAfter,
pathParts.Length - startAfter - (lastPartWasDirectory?0:1));
}
This method attempts to work out if the last part is a filename and drops it if it is.
Calling it with
GetRightPartOfPath(#"C:\my documents\my folder\my other folder\filename.exe", "my folder");
returns
my folder\my other folder
Calling it with
GetRightPartOfPath(#"C:\my documents\my folder\my other folder\", "my folder");
returns the same.
you could use this method to split the path by "\" sign (or "/" in Unix environments). After this you get an array of strings back and you can pick what you need.
public static String[] SplitPath(string path)
{
String[] pathSeparators = new String[]
{
Path.DirectorySeparatorChar.ToString()
};
return path.Split(pathSeparators, StringSplitOptions.RemoveEmptyEntries);
}
I have to strip a file path and get the parent folder.
Say my path is
\\ServerA\FolderA\FolderB\File.jpg
I need to get
File Name = File.jog
Folder it resides in = FolderB
And parent folder = FolderA
I always have to go 2 levels up from where the file resides.
Is there an easier way or is a regular expression the way to go?
FileInfo is your friend:
using System;
using System.IO;
class Test
{
static void Main(string[] args)
{
string file = #"\\ServerA\FolderA\FolderB\File.jpg";
FileInfo fi = new FileInfo(file);
Console.WriteLine(fi.Name); // Prints File.jpg
Console.WriteLine(fi.Directory.Name); // Prints FolderB
Console.WriteLine(fi.Directory.Parent.Name); // Prints FolderA
}
}
string fileName = System.IO.Path.GetFileName(path);
string parent = System.IO.Path.GetDirectoryName(path);
string parentParent = System.IO.Directory.GetParent(parent);
Check out the Directory class (better choice than DirectoryInfo in this case). It does everything you need. You should not use a regex or any other parsing technique.
var fi = new FileInfo(#"\\ServerA\FolderA\FolderB\File.jpg");
fi.Name
fi.Directory.Name
fi.Directory.Parent.Name
You have a few options to do this actually which use actual .net objects instead of regex.
You can use the FileInfo:
FileInfo fileInfo = new FileInfo(#"\\ServerA\FolderA\FolderB\File.jpg");
fileInfo.Name //will give you the file name;
DirectoryInfo directory = fileInfo.Directory; //will give you the parent folder of the file (FolderB);
directory.Parent; //will give you this directories parent folder (FolderA)
If you know for sure that you are always dealing with a file and two directories, try using split:
string s = #"\\ServerA\FolderA\FolderB\File.jpg";
string[] parts = s.Split('\'); // might need '\\'
string file = parts[parts.Length];
string parentDir = parts[parts.Length - 1];
string grandParentDir = parts[parts.Length - 2];