dotnet / dotnet/command-line-api

How to validate that an argument is a valid file path?

Open
#1,832 2 comments 0 reactions 0 assignees View on GitHub
bug
Dominant language
C#
Stars
3.7k
Forks
428
PR merge metrics
No merged PRs in 30d

Description

I need an argument use for file creation or appending (_path_ parameter in `File.AppendAllText` function). As far as I know there are two functions available `LegalFileNamesOnly` and `LegalFilePathsOnly`. The problem is that `LegalFileNamesOnly` validates just file name and so doesn't allow path characters like '\\' or ':'. On the other hand `LegalFilePathsOnly` allows (as expected) path characters ( '\', ':'), but also allows wildcard characters like '*' or '?', which cause the file writing function exception. Also there is not path length validation.

The problem is more serious when net framework 4.x is used. Because `new FileInfo("C:\\*.txt")`, which is legal in .net 6.0 causes an exception and so when the type of argument is FileInfo (like in [Tutorial: Get started with System.CommandLine](https://docs.microsoft.com/en-us/dotnet/standard/commandline/get-started-tutorial) ) the exception will be in ` return await rootCommand.InvokeAsync(args);` and so difficult to be reasonably handled.

### Full example

internal class Program
{
static async Task Main(string[] args)
{
try
{
var fileOption = new Option(
name: "--file",
description: "The file to read and display on the console.")
{ IsRequired = true };

fileOption.LegalFilePathsOnly();

var rootCommand = new RootCommand("Sample app for System.CommandLine");
rootCommand.AddOption(fileOption);

rootCommand.SetHandler((file) =>
{
WriteFile(file);
},
fileOption);

return await rootCommand.InvokeAsync("--file C:\\test*.txt");
//return await rootCommand.InvokeAsync("--file c:\\temp\\testForentitiesbeingtrackedbytheDbContextthevaluesofforeignkeypropertiesindependententitiesarenotchangedwhentherelatedprincipalentityisdeletedThiscanresultinaninconsistentgraphofentitieswherethevaluesofforeignkeypropertiesdonotmatchtherelationshipsinthegraph.txt");

}
finally
{
Console.ReadLine();
}

}

static void WriteFile(FileInfo file)
{
System.IO.File.AppendAllText(file.FullName, "testing text " + DateTime.Now.ToString() + "\n");
}
}

When running on .net 6.0 it fails on `System.IO.File.AppendAllText....` and on framework 4.7.2 it fails on `return await rootCommand...`
in both case with System.ArgumentException: Illegal characters in path.

When the too long filename is used (the commented out line) we get "System.IO.IOException: 'The filename, directory name, or volume label syntax is incorrect. " on net 6.0 and on framework "System.IO.PathTooLongException" on the same lines.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.