How to navigate a few folders up? - c#

One option would be to do System.IO.Directory.GetParent() a few times. Is there a more graceful way of travelling a few folders up from where the executing assembly resides?
What I am trying to do is find a text file that resides one folder above the application folder. But the assembly itself is inside the bin, which is a few folders deep in the application folder.

Other simple way is to do this:
string path = #"C:\Folder1\Folder2\Folder3\Folder4";
string newPath = Path.GetFullPath(Path.Combine(path, #"..\..\"));
Note This goes two levels up. The result would be:
newPath = #"C:\Folder1\Folder2\";
Additional Note
Path.GetFullPath normalizes the final result based on what environment your code is running on windows/mac/mobile/...

if c:\folder1\folder2\folder3\bin is the path then the following code will return the path base folder of bin folder
//string directory=System.IO.Directory.GetParent(Environment.CurrentDirectory).ToString());
string directory=System.IO.Directory.GetParent(Environment.CurrentDirectory).ToString();
ie,c:\folder1\folder2\folder3
if you want folder2 path then you can get the directory by
string directory = System.IO.Directory.GetParent(System.IO.Directory.GetParent(Environment.CurrentDirectory).ToString()).ToString();
then you will get path as c:\folder1\folder2\

You can use ..\path to go one level up, ..\..\path to go two levels up from path.
You can use Path class too.
C# Path class

This is what worked best for me:
string parentOfStartupPath = Path.GetFullPath(Path.Combine(Application.StartupPath, #"../"));
Getting the 'right' path wasn't the problem, adding '../' obviously does that, but after that, the given string isn't usable, because it will just add the '../' at the end.
Surrounding it with Path.GetFullPath() will give you the absolute path, making it usable.

public static string AppRootDirectory()
{
string _BaseDirectory = AppDomain.CurrentDomain.BaseDirectory;
return Path.GetFullPath(Path.Combine(_BaseDirectory, #"..\..\"));
}

Maybe you could use a function if you want to declare the number of levels and put it into a function?
private String GetParents(Int32 noOfLevels, String currentpath)
{
String path = "";
for(int i=0; i< noOfLevels; i++)
{
path += #"..\";
}
path += currentpath;
return path;
}
And you could call it like this:
String path = this.GetParents(4, currentpath);

C#
string upTwoDir = Path.GetFullPath(Path.Combine(System.AppContext.BaseDirectory, #"..\..\"));

The following method searches a file beginning with the application startup path (*.exe folder). If the file is not found there, the parent folders are searched until either the file is found or the root folder has been reached. null is returned if the file was not found.
public static FileInfo FindApplicationFile(string fileName)
{
string startPath = Path.Combine(Application.StartupPath, fileName);
FileInfo file = new FileInfo(startPath);
while (!file.Exists) {
if (file.Directory.Parent == null) {
return null;
}
DirectoryInfo parentDir = file.Directory.Parent;
file = new FileInfo(Path.Combine(parentDir.FullName, file.Name));
}
return file;
}
Note: Application.StartupPath is usually used in WinForms applications, but it works in console applications as well; however, you will have to set a reference to the System.Windows.Forms assembly. You can replace Application.StartupPath by
Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) if you prefer.
I use this strategy to find configuration and resource files. This allows me to share them for multiple applications or for Debug and Release versions of an application by placing them in a common parent folder.

Hiding a looped call to Directory.GetParent(path) inside an static method is the way to go.
Messing around with ".." and Path.Combine will ultimately lead to bugs related to the operation system or simply fail due to mix up between relative paths and absolute paths.
public static class PathUtils
{
public static string MoveUp(string path, int noOfLevels)
{
string parentPath = path.TrimEnd(new[] { '/', '\\' });
for (int i=0; i< noOfLevels; i++)
{
parentPath = Directory.GetParent(parentPath ).ToString();
}
return parentPath;
}
}

this may help
string parentOfStartupPath = Path.GetFullPath(Path.Combine(Application.StartupPath, #"../../")) + "Orders.xml";
if (File.Exists(parentOfStartupPath))
{
// file found
}

If you know the folder you want to navigate to, find the index of it then substring.
var ind = Directory.GetCurrentDirectory().ToString().IndexOf("Folderame");
string productFolder = Directory.GetCurrentDirectory().ToString().Substring(0, ind);

I have some virtual directories and I cannot use Directory methods. So, I made a simple split/join function for those interested. Not as safe though.
var splitResult = filePath.Split(new[] {'/', '\\'}, StringSplitOptions.RemoveEmptyEntries);
var newFilePath = Path.Combine(filePath.Take(splitResult.Length - 1).ToArray());
So, if you want to move 4 up, you just need to change the 1 to 4 and add some checks to avoid exceptions.

Path parsing via System.IO.Directory.GetParent is possible, but would require to run same function multiple times.
Slightly simpler approach is to threat path as a normal string, split it by path separator, take out what is not necessary and then recombine string back.
var upperDir = String.Join(Path.DirectorySeparatorChar, dir.Split(Path.DirectorySeparatorChar).SkipLast(2));
Of course you can replace 2 with amount of levels you need to jump up.
Notice also that this function call to Path.GetFullPath (other answers in here) will query whether path exists using file system. Using basic string operation does not require any file system operations.

Related

How to get parent directory in a path c#?

it is my path example E:\test\img\sig.jpg
I want to get E:\test\img to create directory
i try split but it be img
so I try function Directory.CreateDirectory and the path is E:\test\img\sig.jpg\
say me a ideas?
The recommended way is to use Path.GetDirectoryName():
string file = #"E:\test\img\sig.jpg";
string path = Path.GetDirectoryName(file); // results in #"E:\test\img"
Use Path.GetDirectoryName which returns the directory information for the specified path string.
string directoryName = Path.GetDirectoryName(filePath);
The Path class contains a lot of useful methods for path handling, which are more reliable than manual string manipulation:
var directoryComponent = Path.GetDirectoryName(#"E:\test\img\sig.jpg");
// yields `E:\test\img`
For completeness, I'd like to mention Path.Combine, which does the opposite:
var dirAndFile = Path.Combine(#"E:\test\img", "sig.jpg");
// no more checking for trailing slashes, hooray!
To create the directory, you can use Directory.Create. Note that it is not necessary to check if the directory exists first.
You can try this code to find the directory name.
System.IO.FileInfo fi = new System.IO.FileInfo(#"E:\test\img\sig.jpg");
string dirname = fi.DirectoryName;
and to create the directory
Directory.CreateDirectory(dirname );
Another solution can be :
FileInfo f = new FileInfo(#"E:\test\img\sig.jpg");
if (f.Exists)
{
string dirName= f.DirectoryName;
}

Get folder on in same directory as App domain path

I have an asp.net web app and i need to get the string path of a folder in the same directory as my web app.
Currently im using this code to get the add domain path.
string appPath = HttpRuntime.AppDomainAppPath;
Which returns "c:/path/webapp", i need "c:/path/folder".
Thanks.
If you'd like a more generic approach that doesn't require knowing the starting folder:
//NOTE: using System.IO;
String startPath = Path.GetDirectoryName(HttpRuntime.AppDomainAppPath);
Int32 pos = startPath.LastIndexOf(Path.DirectorySeparatorChar);
String newPath = Path.Combine(startPath.Substring(0, pos), "folder"); //replace "folder" if it's really something else, of course
This way, whatever directory your web app is running from, you can get it, reduce it by one level, and tack on "folder" to get your new sibling directory.
You can use String.Replace method.
Returns a new string in which all occurrences of a specified string in
the current instance are replaced with another specified string.
string appPath = HttpRuntime.AppDomainAppPath;
appPath = appPath.Replace("webapp", "folder");
Here is a DEMO.
Thanks to DonBoitnott comments, here is the right answer;
string appPath = #"C:\mydir\anotherdir\webapp\thirddir\webapp";
int LastIndex = appPath.LastIndexOf("webapp", StringComparison.InvariantCulture);
string RealappPath = Path.Combine(appPath.Substring(0, LastIndex), "folder");
Console.WriteLine(RealappPath);
This will print;
C:\mydir\anotherdir\webapp\thirddir\folder

Get path to executable from command (as cmd does)

Given a command-line style path to a command such as bin/server.exe or ping, how can I get the full path to this executable (as cmd or Process.Start would resolve it)?
I tried Path.GetFullPath, but it always expands relative to the working directory. It expands bin/server.exe correctly, however given ping it returns c:\users\matt\ping (non-existent). I want c:\Windows\system32\ping.exe.
Edit: I would like the same behaviour as cmd. Some considerations:
When there is a local executable with the same name as one in the path, cmd prefers the local one
cmd can expand the command server to server.bat or server.exe (adding the file extension)
I also tried Windows' command-line tool called where . It does almost I want:
Displays the location of files that match the search pattern. By default, the search is done along the current directory and in the paths specified by the PATH environment variable.
>where ping
C:\Windows\System32\PING.EXE
>where bin\server
INFO: Could not find files for the given pattern(s).
(This question is hard to search around because of the two different meanings of the word 'path')
Considering PATHEXT too, stealing from Serj-Tm's answer (sorry! +1 to him):
public static string WhereSearch(string filename)
{
var paths = new[]{ Environment.CurrentDirectory }
.Concat(Environment.GetEnvironmentVariable("PATH").Split(';'));
var extensions = new[]{ String.Empty }
.Concat(Environment.GetEnvironmentVariable("PATHEXT").Split(';')
.Where(e => e.StartsWith(".")));
var combinations = paths.SelectMany(x => extensions,
(path, extension) => Path.Combine(path, filename + extension));
return combinations.FirstOrDefault(File.Exists);
}
Sorry the indentation's a bit all-over-the-place - I was trying to make it not scroll. I don't know if the StartsWith check is really necessary - I'm not sure how CMD copes with pathext entries without a leading dot.
public static string GetFullPath(string filename)
{
return new[]{Environment.CurrentDirectory}
.Concat(Environment.GetEnvironmentVariable("PATH").Split(';'))
.Select(dir => Path.Combine(dir, filename))
.FirstOrDefault(path => File.Exists(path));
}
If you're only interested in searching the current directory and the paths specified in the PATH environment variable, you can use this snippet:
public static string GetFullPath(string fileName)
{
if (File.Exists(fileName))
return Path.GetFullPath(fileName);
var values = Environment.GetEnvironmentVariable("PATH");
foreach (var path in values.Split(';'))
{
var fullPath = Path.Combine(path, fileName);
if (File.Exists(fullPath))
return fullPath;
}
return null;
}
You have to search the entire disk.
Windows can respond to things like, iexplore, ping, cmd, etc, because they are in the registry under this key:
HKEY_LOCAL_MACHINE
SOFTWARE
Microsoft
Windows
CurrentVersion
App Paths
The only other way is to search the entire disk for the application.
EDIT: My understanding was, that you want to search for any random executable name, not the ones that are already known to Windows..
internal class Program
{
static void Main(string[] args)
{
string fullPath = GetExactPathFromEnvironmentVar("ping.exe");
if (!string.IsNullOrWhiteSpace(fullPath))
Console.WriteLine(fullPath);
else
Console.WriteLine("Not found");
}
static string GetExactPathFromEnvironmentVar(string program)
{
var pathVar = System.Environment.GetEnvironmentVariable("PATH");
string[] folders = pathVar.Split(';');
foreach (var folder in folders)
{
string path = Path.Combine(folder, program);
if (File.Exists(path))
{
return path;
}
}
return null;
}
}
HTH

Using GetEnvironmentVariable method to move files

I was using hard-coded directory path to Program Files to move file. I would now like to use the correct method to find the folder in Program Files.
I have found this method doing some Googling and it is what i would like to use:
static string ProgramFilesx86()
{
if( 8 == IntPtr.Size || (!String.IsNullOrEmpty(Environment.GetEnvironmentVariable("PROCESSOR_ARCHITEW6432"))))
{
return Environment.GetEnvironmentVariable("ProgramFiles(x86)");
}
return Environment.GetEnvironmentVariable("ProgramFiles");
}
I unfortunately am not sure how to implement and use this method.
Where do i insert the method in my app?
How do i use the above instead of this:
if (File.Exists(#"C:\PROGRA~1\TEST\ok.txt"))
File.Delete(#"C:\PROGRA~1\TEST\ok.txt");
File.Copy(#"C:\PROGRA~1\PROGRAMFOLDER\ok.txt", #"C:\PROGRA~1\TEST\ok.txt");
It's much easier to get the special folders like Program Files using
Environment.SpecialFolders
string programFilesFolder =
Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86)
Continuing that example you could do something like this
string pathToFile =
Path.Combine(programFilesFolder, #"TEST\ok.txt");
if (File.Exists(pathToFile))
File.Delete(pathToFile);
UPDATE
Modified the code example to always get the 32-bit Program Files folder whether you're running 32- or 64-bit OS as #Mario pointed out that's what your original code was doing.
string fileName = Path.Combine( ProgramFilesx86(), applicationPath, #"ok.txt");
if (File.Exists( fileName ) )
{
File.remove( fileName );
}
string sourceFile = Path.Combine( ProgramFilesx86(), #"\PROGRAMFOLDER", "ok.txt" );
File.Copy( sourceFile, fileName);
Edit:
You should not use this method. The program folder depends on the capability of the programs and not the system! You must know whether they install to the ProgramFiles or ProgramFilesX86 folder.
And then use Eric J.'s answer.
string sourceFolder =
Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles);
string source =
Path.Combine(sourceFolder, #"ok.txt");
string targetFolderPath =
Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
string target = Path.Combine(targetFolderPath, #"ok.txt");
if (File.Exists(source))
File.Delete(source);
File.Copy(targetFolderPath, source);

Moving files based on name to the corresponding folder

Hello everyone and well met! I have tried a lot of different methods/programs to try and solve my problem. I'm a novice programmer and have taken a Visual Basic Class and Visual C# class.
I'm working with this in C#
I started off by making a very basic move file program and it worked fine for one file but as I mentioned I will be needing to move a ton of files based on name
What I am trying to do is move .pst (for example dave.pst) files from my exchange server based on username onto a backup server in the users folder (folder = dave) that has the same name as the .pst file
The ideal program would be:
Get files from the folder with the .pst extension
Move files to appropriate folder that has the same name in front of the .pst file extension
Update:
// String pstFileFolder = #"C:\test\";
// var searchPattern = "*.pst";
// var extension = ".pst";
//var serverFolder = #"C:\test3\";
// String filename = System.IO.Path.GetFileNameWithoutExtension(pstFileFolder);
// Searches the directory for *.pst
DirectoryInfo sourceDirectory = new DirectoryInfo(#"C:\test\");
String strTargetDirectory = (#"C:\test3\");
Console.WriteLine(sourceDirectory);
Console.ReadKey(true);>foreach (FileInfo file in sourceDirectory.GetFiles()) {
Console.WriteLine(file);
Console.ReadKey(true);
// Try to create the directory.
System.IO.Directory.CreateDirectory(strTargetDirectory);
file.MoveTo(strTargetDirectory + "\\" + file.Name);
}
This is just a simple copy procedure. I'm completely aware. The
Console.WriteLine(file);
Console.ReadKey(true);
Are for verification purpose right now to make sure I'm getting the proper files and I am. Now I just need to find the folder based on the name of the .pst file(the folder for the users are already created), make a folder(say 0304 for the year), then copy that .pst based on the name.
Thanks a ton for your help guys. #yuck, thanks for the code.
Have a look at the File and Directory classes in the System.IO namespace. You could use the Directory.GetFiles() method to get the names of the files you need to transfer.
Here's a console application to get you started. Note that there isn't any error checking and it makes some assumptions about how the files are named (e.g. that they end with .pst and don't contain that elsewhere in the name):
private static void Main() {
var pstFileFolder = #"C:\TEMP\PST_Files\";
var searchPattern = "*.pst";
var extension = ".pst";
var serverFolder = #"\\SERVER\PST_Backup\";
// Searches the directory for *.pst
foreach (var file in Directory.GetFiles(pstFileFolder, searchPattern)) {
// Exposes file information like Name
var theFileInfo = new FileInfo(file);
// Gets the user name based on file name
// e.g. DaveSmith.pst would become DaveSmith
var userName = theFileInfo.Name.Replace(extension, "");
// Sets up the destination location
// e.g. \\SERVER\PST_Backup\DaveSmith\DaveSmith.pst
var destination = serverFolder + userName + #"\" + theFileInfo.Name;
File.Move(file, destination);
}
}
System.IO is your friend in this case ;)
First, Determine file name by:
String filename = System.IO.Path.GetFileNameWithoutExtension(SOME_PATH)
To make path to new folder, use Path.Combine:
String targetDir = Path.Combine(SOME_ROOT_DIR,filename);
Next, create folder with name based on given fileName
System.IO.Directory.CreateDirectory(targetDir);
Ah! You need to have name of file, but with extension this time. Path.GetFileName:
String fileNameWithExtension = System.IO.Path.GetFileName(SOME_PATH);
And you can move file (by File.Move) to it:
System.IO.File.Move(SOME_PATH,Path.Combine(targetDir,fileNameWithExtension)
Laster already show you how to get file list in folder.
I personally prefer DirectoryInfo because it is more object-oriented.
DirectoryInfo sourceDirectory = new DirectoryInfo("C:\MySourceDirectoryPath");
String strTargetDirectory = "C:\MyTargetDirectoryPath";
foreach (FileInfo file in sourceDirectory.GetFiles())
{
file.MoveTo(strTargetDirectory + "\\" + file.Name);
}

Categories