问题
i would like to get the original folder name by dynamic path and username, and without Windows default directory
For example,
C:\Users\dynamic user\Desktop\History\2014-11-03\Spreadsheets\excel.xls
C:\Users\dynamic user\Desktop\History\record.xls
In this case, i want it to return "History" for excel.xls & record.xls. I tried to use GetFilename() method. But it just returns
Spreadsheets - excel.xls
History - record.xls
Is it possible to achieve? Thanks for your help.
回答1:
Yes, as documented of Path.GetFileName;
Returns the file name and extension of the specified path string.
One solution can be delete your Desktop
path and split with Path.DirectorySeparatorChar character and gets second element.
For example;
string path = @"C:\Users\dynamic user\Desktop\History\2014-11-03\Spreadsheets\excel.xls";
var desktop = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
path = path.Replace(desktop, "");
var history = path.Split(Path.DirectorySeparatorChar)[1];
Console.WriteLine(history); // History
Remember, Environment.SpecialFolder.Desktop returns current user desktop information.
回答2:
So if I've understood you want to find the common base path from a set of paths? There isn't any built in function to do this, so your back to string matching and some LINQ gives this:
static void Main(string[] args)
{
List<string> paths = new List<string>()
{
@"C:\Users\dynamic user\Desktop\History\2014-11-03\Spreadsheets\excel.xls"
,@"C:\Users\dynamic user\Desktop\History\record.xls"
,@"C:\Users\dynamic user\Desktop\History\2014-11-23\Spreadsheets\excel.xls"
,@"C:\Users\dynamic user\Desktop\History\2014-11-03\excel.xls"
};
Console.WriteLine("The common base path of:");
paths.ForEach(f => Console.WriteLine(f));
Console.WriteLine("is");
Console.WriteLine(FindBasePath(paths));
Console.ReadLine();
}
static string FindBasePath(List<string> paths)
{
string basePath = String.Empty;
foreach (string path in paths)
{
string dirName = Path.GetDirectoryName(path);
if (paths.All(f => Path.GetDirectoryName(f).Contains(dirName)))
return basePath = dirName;
}
return basePath;
}
Forgot to add comment as to what we're doing. Basically we loop over every path, and get the name of the directory, then if ALL the paths contains this string, it must be the common root directory.
Note this will check every path against every other path...and could be improved.
You could also do it one LINQ statement:
paths.Select(f => Path.GetDirectoryName(f)
.Select(f => paths.All(g => g.Contains(f)) ? f : "")
.Where(f => !String.IsNullOrEmpty(f))
.First()
回答3:
There is no in-built way of doing what you want. The following code should do the trick:
public static string GetFolderByLevel(this string path, string baseFolderName, int level)
{
if (path == null)
throw new ArgumentNullException("path");
if (baseFolderName == null)
throw new ArgumentNullException("baseFolderName");
var pathWithoutFile = Path.GetDirectoryName(path);
var folders = pathWithoutFile.ToString().Split(Path.DirectorySeparatorChar);
int baseFolderLevel = -1;
for (int i = 0; i < folders.Length; ++i)
{
if (string.Compare(folders[i], baseFolderName, true) == 0)
{
baseFolderLevel = i;
break;
}
}
if (baseFolderLevel == -1)
throw new ArgumentException(string.Format("Folder '{0}' could not be found in specified path: {1}", baseFolderName, path), "baseFolderName");
int index = baseFolderLevel + level;
if (-1 < index && index < folders.Length)
{
return folders[index];
}
else
throw new ArgumentOutOfRangeException(string.Format("Specified level is out of range."));
}
Now you can use it like:
string path = @"C:\Users\dynamic user\Desktop\History\Peter\record.xls";
path.GetFolderByLevel("Desktop", -2); //returns "Users"
path.GetFolderByLevel("History", 0); //returns "History"
path.GetFolderByLevel("Desktop", 1); //returns "History"
In your case, if I'm not mistaken, your are looking for path.GetFolderByLevel("Desktop", 1);
UPDATE: I've modified the previous solution so that you can specify the base folder with a partial or full path:
public static string GetFolderByLevel(this string path, string baseFolderPath, int level)
{
if (path == null)
throw new ArgumentNullException("path");
if (baseFolderPath == null)
throw new ArgumentNullException("baseFolderName");
var pathFolders = path.Split(new char[] {Path.DirectorySeparatorChar}, StringSplitOptions.RemoveEmptyEntries);
var basePathFolders = baseFolderPath.Split(new char[] { Path.DirectorySeparatorChar }, StringSplitOptions.RemoveEmptyEntries);
int baseFolderIndex = -1;
int folderCounter = 0;
for (int i = 0; i < pathFolders.Length; ++i)
{
if (string.Compare(pathFolders[i], basePathFolders[folderCounter], true) == 0)
{
if (++folderCounter == basePathFolders.Length)
{
baseFolderIndex = i;
break;
}
}
else
{
folderCounter = 0;
}
}
if (baseFolderIndex < 0)
throw new ArgumentException(string.Format("Folder '{0}' could not be found in specified path: {1}", baseFolderPath, path), "baseFolderName");
int index = baseFolderIndex + level;
if (-1 < index && index < pathFolders.Length)
{
return pathFolders[index];
}
else
throw new ArgumentOutOfRangeException(string.Format("Specified level is out of range."));
}
Now you could use it like: path.GetFolderByLevel(Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory), 1);
An additional advantage would be in case of having nested folders with the same name, you can specify the unique partial path of the base folder to make sure the method picks the right one.
回答4:
Or this:
var dir_path = Path.GetDirectoryName(@"C:\your\path\with\file.ext");
var dir_name = new DirectoryInfo(dir_path).Name;
来源:https://stackoverflow.com/questions/26709568/get-specific-level-of-directory