I'm writing a tool that will manipulate files via the command line, and what I would like to do is be able to supply a path to a file that is not necessarily in the current working directory.

For example, if I run my software with the command line paremeter "*.jpg", I know that I can use DirectoryInfo(Environment.CurrentDirectory); and then GetFiles(args[0]); to get the files in my current directory, but how can I make it change the path on the fly, if I were to say use "..\*.jpg" or something similar? I tried doing this within the DirectoryInfo constructor, and it threw an exception saying that I could not use ".." to move up a folder.

5
Contributors
12
Replies
14
Views
7 Years
Discussion Span
Last Post by Matt Gudmundson

Actually, let me rephrase that a bit..

Lets say I want to make a very simple tool to list the structure of a directory, just like "dir" or "ls" in linux. If I were to just type "dir", I can easily list the contents of the current directory. But what if I want to supply a path relative to my current working directory? How can I get the code to recognize this, and change the working directory accordingly?

To move up in a directory use the Parent property of DirectoryInfo.
DirectoryInfo MyParentDir = MyCurrentDir.Parent;and then say something like:
Console.WriteLine("The parent directory of '{0}' is '{1}'", MyCurrentDir.Name, MyParentDir .Name);

You can also use Uri

private void button3_Click(object sender, EventArgs e)
{
string baseDir = IncludeTrailingPathDelimiter(Environment.CurrentDirectory);
const string arg = @"..\";
Uri baseUri = new Uri(baseDir, UriKind.Absolute);
Uri resolvedUri = new Uri(baseUri, arg);
Console.WriteLine(string.Format("CWD     : '{0}'", baseUri.LocalPath));
Console.WriteLine(string.Format("arg     : '{0}'", arg));
Console.WriteLine(string.Format("Combined: '{0}'", resolvedUri.LocalPath));
System.Diagnostics.Debugger.Break();
}
private static string IncludeTrailingPathDelimiter(string Dir)
{
if (string.IsNullOrEmpty(Dir))
return string.Empty;
else if (!Dir.EndsWith(Convert.ToString(Path.DirectorySeparatorChar)))
return (Dir + Convert.ToString(Path.DirectorySeparatorChar));
else
return Dir;
}

Results in:

CWD     : 'C:\dotnetwin\daniweb\bin\Debug\'
arg     : '..\'
Combined: 'C:\dotnetwin\daniweb\bin\'

I don't think that quite answers what i'm looking for.. At least I can't see how to make it work, though.

Lets give an example then... Say I have the following code:

static void Main(string[] args) {

DirectoryInfo currentDir = new DirectoryInfo(Environment.CurrentDirectory);

DirectoryInfo[] dirList = currentDir.GetDirectories();
FileInfo[] fileList = currentDir.GetFiles();

foreach (DirectoryInfo dir in dirList)
Console.WriteLine("Directory: {0}", dir);
foreach (FileInfo file in fileList)
Console.WriteLine("File: {0}", file);
}

If I ran this from my folder "E:\MyDir\" for example, it would output this:

Directory: temp
File: Document.txt

How could I modify this to accept a relative path as an argument? By relative, I want to be able to go forward and backward as well.. so if I were to run the file dir ..\ or dir temp that it would be able to show me the contents of either folder?

Also, if I wanted to also apply a filter to the files that show up (say, for example, I want to type dir temp\*.bmp , it would be able to feed the *.bmp part into the GetFiles(@"*.bmp"); .

I just can't wrap my head around what method I should use for this. Should I be using a different set of classes and methods?

Here is an example of a feed from the command line. I tested with "app.exe ..\..\" from the command line and it worked:

DirectoryInfo currentDir = new DirectoryInfo(args[0]);// (Environment.CurrentDirectory);

Second part, with filename search spec:

FileInfo[] fileList = currentDir.GetFiles(args[1]);//();

I tested this using "app.exe ..\..\ *.csproj". Note the space between "..\..\" and "*.csproj".

Here is the code you posted with the changes. I just tested it passing in "c:\ *.*" and it worked find--again, note the space between the arguments. You will want to ensure you don't access "args" outside it's Length, or you will get an exception.

static void Main(string[] args)
{
foreach (string s in args)
Console.WriteLine("arg: " + s);

DirectoryInfo currentDir = new DirectoryInfo(args[0]);// (Environment.CurrentDirectory);

DirectoryInfo[] dirList = currentDir.GetDirectories();
FileInfo[] fileList = currentDir.GetFiles(args[1]);//();

foreach (DirectoryInfo dir in dirList)
Console.WriteLine("Directory: {0}", dir);
foreach (FileInfo file in fileList)
Console.WriteLine("File: {0}", file);
}

The problems I have with this solution, however, is that it feels strange to have to add the space between the path and the filename.. I'm sure there is some method out there to parse out the information if a single string is given.

Also, this would not work if args[] has a 0 length, because the args[0] would be at best null, or "", and either one would cause the program to fail. I've tested this by using both DirectoryInfo currentDir = new DirectoryInfo(); and DirectoryInfo currentDir = new DirectoryInfo(""); .

Also... args[0] may not be the specific location of my path in every case. I eventually want to be able to parse other parameters out of the string. But that is another issue to be dealt with.

1) The problems I have with this solution, however, is that it feels strange to have to add the space between the path and the filename.. I'm sure there is some method out there to parse out the information if a single string is given.

2) Also, this would not work if args[] has a 0 length, because the args[0] would be at best null, or "", and either one would cause the program to fail. I've tested this by using both DirectoryInfo currentDir = new DirectoryInfo(); and DirectoryInfo currentDir = new DirectoryInfo(""); .

3) Also... args[0] may not be the specific location of my path in every case. I eventually want to be able to parse other parameters out of the string. But that is another issue to be dealt with.

1) It appeared you wanted to utilize two params--sorry. You are correct that you can parse the filename out of the path.
2) True--that's why I told you to not exceed Length...
3) too many unknowns...

I will attempt to help you with your parse in item 1, to utilize only one parameter in args. BRB

Here it is:

string path = Path.GetDirectoryName(args[0]);
string filespec = Path.GetFileName(args[0]);

Console.WriteLine("Path: " + path);
Console.WriteLine("Filespec: " + filespec);
Console.Read();

Tested with "C:\*.*" on command line.
I assume you know how to check args and substitute current directory with *.* if the user does not supply args?

I assume you know how to check args and substitute current directory with *.* if the user does not supply args?

Yeah, should be simple enough.

if (args.Length < 1)
currentFolder = Environment.CurrentFolder;
else
currentFolder = args[0];

and then just substitute currentFolder into the definition.

That will work for now, but ultimately i'll want to have the program be a bit smarter about handling the command line parameters... Thanks

I'm writing a tool that will manipulate files via the command line, and what I would like to do is be able to supply a path to a file that is not necessarily in the current working directory.

For example, if I run my software with the command line paremeter "*.jpg", I know that I can use DirectoryInfo(Environment.CurrentDirectory); and then GetFiles(args[0]); to get the files in my current directory, but how can I make it change the path on the fly, if I were to say use "..\*.jpg" or something similar? I tried doing this within the DirectoryInfo constructor, and it threw an exception saying that I could not use ".." to move up a folder.

DirectoryInfo dir = new DirectoryInfo(Environment.CurrentDirectory);
string dirA = dir.Parent.FullName;

Try that.

Edited by Matt Gudmundson: n/a