Respostas:
Tentar usar System.IO.Path.IsPathRooted
? Ele também retorna true
para caminhos absolutos.
System.IO.Path.IsPathRooted(@"c:\foo"); // true
System.IO.Path.IsPathRooted(@"\foo"); // true
System.IO.Path.IsPathRooted("foo"); // false
System.IO.Path.IsPathRooted(@"c:1\foo"); // surprisingly also true
System.IO.Path.GetFullPath(@"c:1\foo");// returns "[current working directory]\1\foo"
IsPathRooted
: evitar acessar o sistema de arquivos ou lançar exceções para entrada inválida.
IsPathRooted
, certamente não era nada significativo. A GetFullPath
linha foi incluída para que o caminho sendo avaliado pudesse ser observado
Path.IsPathRooted(path)
&& !Path.GetPathRoot(path).Equals(Path.DirectorySeparatorChar.ToString(), StringComparison.Ordinal)
A condição acima:
false
na maioria dos casos em que o formato de path
é inválido (em vez de lançar uma exceção)true
apenas se path
inclui o volumeEm cenários como o apresentado pelo OP, pode, portanto, ser mais adequado do que as condições nas respostas anteriores. Ao contrário da condição acima:
path == System.IO.Path.GetFullPath(path)
lança exceções em vez de retornar false
nestes cenários:
System.IO.Path.IsPathRooted(path)
retorna true
se path
começa com um único separador de diretório.Finalmente, aqui está um método que envolve a condição acima e também exclui as possíveis exceções restantes:
public static bool IsFullPath(string path) {
return !String.IsNullOrWhiteSpace(path)
&& path.IndexOfAny(System.IO.Path.GetInvalidPathChars().ToArray()) == -1
&& Path.IsPathRooted(path)
&& !Path.GetPathRoot(path).Equals(Path.DirectorySeparatorChar.ToString(), StringComparison.Ordinal);
}
EDIT: EM0 fez um bom comentário e resposta alternativa abordando o curioso caso de caminhos como C:
e C:dir
. Para ajudar a decidir como você pode querer lidar com tais caminhos, você pode querer mergulhar fundo no MSDN -> aplicativos de desktop do Windows -> Desenvolver -> Tecnologias de desktop -> Acesso e armazenamento de dados -> Sistemas de arquivos locais - -> Gerenciamento de arquivos -> Sobre gerenciamento de arquivos -> Criação, exclusão e manutenção de arquivos -> Arquivos de nomenclatura, caminhos e namespaces -> Caminhos totalmente qualificados versus caminhos relativos
Para funções da API do Windows que manipulam arquivos, os nomes dos arquivos podem frequentemente ser relativos ao diretório atual, enquanto algumas APIs requerem um caminho totalmente qualificado. Um nome de arquivo é relativo ao diretório atual se não começar com um dos seguintes:
- Um nome UNC de qualquer formato, que sempre começa com dois caracteres de barra invertida ("\"). Para obter mais informações, consulte a próxima seção.
- Um designador de disco com uma barra invertida, por exemplo "C: \" ou "d: \".
- Uma única barra invertida, por exemplo, "\ diretório" ou "\ arquivo.txt". Isso também é conhecido como um caminho absoluto.
Se um nome de arquivo começar apenas com um designador de disco, mas não com a barra invertida após os dois pontos, ele será interpretado como um caminho relativo para o diretório atual na unidade com a letra especificada. Observe que o diretório atual pode ou não ser o diretório raiz, dependendo de como foi definido durante a operação de "alteração de diretório" mais recente nesse disco. Os exemplos deste formato são os seguintes:
- "C: tmp.txt" refere-se a um arquivo chamado "tmp.txt" no diretório atual da unidade C.
- "C: tempdir \ tmp.txt" refere-se a um arquivo em um subdiretório do diretório atual na unidade C.
[...]
Pergunta antiga, mas mais uma resposta aplicável. Se você precisa garantir que o volume seja incluído em um caminho local, você pode usar System.IO.Path.GetFullPath () desta forma:
if (template == System.IO.Path.GetFullPath(template))
{
; //template is full path including volume or full UNC path
}
else
{
if (useCurrentPathAndVolume)
template = System.IO.Path.GetFullPath(template);
else
template = Assembly.GetExecutingAssembly().Location
}
GetFullPath
acessa o sistema de arquivos e pode lançar uma série de exceções possíveis. Veja minha resposta ( stackoverflow.com/a/35046453/704808 ) para uma alternativa que ainda garante um caminho completo.
Com base na resposta do weir : isso não lança para caminhos inválidos, mas também retorna false
para caminhos como "C:", "C: dirname" e "\ path".
public static bool IsFullPath(string path)
{
if (string.IsNullOrWhiteSpace(path) || path.IndexOfAny(Path.GetInvalidPathChars()) != -1 || !Path.IsPathRooted(path))
return false;
string pathRoot = Path.GetPathRoot(path);
if (pathRoot.Length <= 2 && pathRoot != "/") // Accepts X:\ and \\UNC\PATH, rejects empty string, \ and X:, but accepts / to support Linux
return false;
if (pathRoot[0] != '\\' || pathRoot[1] != '\\')
return true; // Rooted and not a UNC path
return pathRoot.Trim('\\').IndexOf('\\') != -1; // A UNC server name without a share name (e.g "\\NAME" or "\\NAME\") is invalid
}
Observe que isso retorna resultados diferentes no Windows e no Linux, por exemplo, "/ path" é absoluto no Linux, mas não no Windows.
Teste de unidade:
[Test]
public void IsFullPath()
{
bool isWindows = Environment.OSVersion.Platform.ToString().StartsWith("Win"); // .NET Framework
// bool isWindows = System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(OSPlatform.Windows); // .NET Core
// These are full paths on Windows, but not on Linux
TryIsFullPath(@"C:\dir\file.ext", isWindows);
TryIsFullPath(@"C:\dir\", isWindows);
TryIsFullPath(@"C:\dir", isWindows);
TryIsFullPath(@"C:\", isWindows);
TryIsFullPath(@"\\unc\share\dir\file.ext", isWindows);
TryIsFullPath(@"\\unc\share", isWindows);
// These are full paths on Linux, but not on Windows
TryIsFullPath(@"/some/file", !isWindows);
TryIsFullPath(@"/dir", !isWindows);
TryIsFullPath(@"/", !isWindows);
// Not full paths on either Windows or Linux
TryIsFullPath(@"file.ext", false);
TryIsFullPath(@"dir\file.ext", false);
TryIsFullPath(@"\dir\file.ext", false);
TryIsFullPath(@"C:", false);
TryIsFullPath(@"C:dir\file.ext", false);
TryIsFullPath(@"\dir", false); // An "absolute", but not "full" path
// Invalid on both Windows and Linux
TryIsFullPath(null, false, false);
TryIsFullPath("", false, false);
TryIsFullPath(" ", false, false);
TryIsFullPath(@"C:\inval|d", false, false);
TryIsFullPath(@"\\is_this_a_dir_or_a_hostname", false, false);
TryIsFullPath(@"\\is_this_a_dir_or_a_hostname\", false, !isWindows);
TryIsFullPath(@"\\is_this_a_dir_or_a_hostname\\", false, !isWindows);
}
private static void TryIsFullPath(string path, bool expectedIsFull, bool expectedIsValid = true)
{
Assert.AreEqual(expectedIsFull, PathUtils.IsFullPath(path), "IsFullPath('" + path + "')");
if (expectedIsFull)
{
Assert.AreEqual(path, Path.GetFullPath(path));
}
else if (expectedIsValid)
{
Assert.AreNotEqual(path, Path.GetFullPath(path));
}
else
{
Assert.That(() => Path.GetFullPath(path), Throws.Exception);
}
}
Para verificar se um caminho é totalmente qualificado (MSDN) :
public static bool IsPathFullyQualified(string path)
{
var root = Path.GetPathRoot(path);
return root.StartsWith(@"\\") || root.EndsWith(@"\");
}
É um pouco mais simples do que o que já foi proposto e ainda retorna falso para caminhos relativos ao drive como C:foo
. Sua lógica é baseada diretamente na definição do MSDN de "totalmente qualificado" e não encontrei nenhum exemplo de mau comportamento.
Curiosamente, no entanto, o .NET Core 2.1 parece ter um novo método Path.IsPathFullyQualified
que usa um método interno PathInternal.IsPartiallyQualified
(localização do link exata em 17/04/2018).
Para a posteridade e melhor autocontenção deste post, aqui está a implementação deste último para referência:
internal static bool IsPartiallyQualified(ReadOnlySpan<char> path)
{
if (path.Length < 2)
{
// It isn't fixed, it must be relative. There is no way to specify a fixed
// path with one character (or less).
return true;
}
if (IsDirectorySeparator(path[0]))
{
// There is no valid way to specify a relative path with two initial slashes or
// \? as ? isn't valid for drive relative paths and \??\ is equivalent to \\?\
return !(path[1] == '?' || IsDirectorySeparator(path[1]));
}
// The only way to specify a fixed path that doesn't begin with two slashes
// is the drive, colon, slash format- i.e. C:\
return !((path.Length >= 3)
&& (path[1] == VolumeSeparatorChar)
&& IsDirectorySeparator(path[2])
// To match old behavior we'll check the drive character for validity as the path is technically
// not qualified if you don't have a valid drive. "=:\" is the "=" file's default data stream.
&& IsValidDriveChar(path[0]));
}
Esta é a solução que uso
public static bool IsFullPath(string path)
{
try
{
return Path.GetFullPath(path) == path;
}
catch
{
return false;
}
}
Funciona da seguinte maneira:
IsFullPath(@"c:\foo"); // true
IsFullPath(@"C:\foo"); // true
IsFullPath(@"c:\foo\"); // true
IsFullPath(@"c:/foo"); // false
IsFullPath(@"\foo"); // false
IsFullPath(@"foo"); // false
IsFullPath(@"c:1\foo\"); // false
C:\foo\..\foo
ouC:\foo\.\.\.
Chame a seguinte função:
Path.IsPathFullyQualified(@"c:\foo")
Documento MSDN: Método Path.IsPathFullyQualified
A citação útil do documento MSDN é a seguinte:
Este método lida com caminhos que usam o separador de diretório alternativo. É um erro frequente presumir que os caminhos com raiz ( IsPathRooted (String) ) não são relativos. Por exemplo, "C: a" é relativo à unidade, ou seja, é resolvido em relação ao diretório atual para C: (com raiz, mas relativo). "C: \ a" está enraizado e não é relativo, ou seja, o diretório atual não é usado para modificar o caminho.
Não tenho certeza do que você quer dizer com caminho completo (embora, supondo que você queira dizer não relativo a partir da raiz), bem, você pode usar a classe Path para ajudá-lo a trabalhar com caminhos de sistema de arquivos físicos, que devem abranger você para a maioria das eventualidades.