Respuestas:
Intente usar System.IO.Path.IsPathRooted
? También regresa true
para rutas absolutas.
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 el acceso al sistema de archivos o lanzar excepciones para entradas no válidas.
IsPathRooted
, ciertamente no era nada significativo. La GetFullPath
línea se incluyó para que se pudiera observar el camino que se está evaluando
Path.IsPathRooted(path)
&& !Path.GetPathRoot(path).Equals(Path.DirectorySeparatorChar.ToString(), StringComparison.Ordinal)
La condición anterior:
false
en la mayoría de los casos donde el formato de path
no es válido (en lugar de lanzar una excepción)true
solo si path
incluye el volumenEn escenarios como el que planteó el OP, por lo tanto, puede ser más adecuado que las condiciones en las respuestas anteriores. A diferencia de la condición anterior:
path == System.IO.Path.GetFullPath(path)
arroja excepciones en lugar de regresar false
en estos escenarios:
System.IO.Path.IsPathRooted(path)
devuelve true
si path
comienza con un solo separador de directorio.Finalmente, aquí hay un método que envuelve la condición anterior y también excluye las posibles excepciones 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);
}
EDITAR: EM0 hizo un buen comentario y respuesta alternativa abordando el curioso caso de caminos como C:
y C:dir
. Para ayudar a decidir cómo desea manejar tales rutas, es posible que desee profundizar en MSDN -> Aplicaciones de escritorio de Windows -> Desarrollar -> Tecnologías de escritorio -> Acceso y almacenamiento de datos -> Sistemas de archivos locales - -> Administración de archivos -> Acerca de la administración de archivos -> Creación, eliminación y mantenimiento de archivos -> Asignación de nombres a archivos, rutas y espacios de nombres -> Rutas totalmente calificadas frente a rutas relativas
Para las funciones de la API de Windows que manipulan archivos, los nombres de los archivos a menudo pueden ser relativos al directorio actual, mientras que algunas API requieren una ruta completamente calificada. Un nombre de archivo es relativo al directorio actual si no comienza con uno de los siguientes:
- Un nombre UNC de cualquier formato, que siempre comienza con dos caracteres de barra invertida ("\"). Para obtener más información, consulte la siguiente sección.
- Un designador de disco con barra invertida, por ejemplo, "C: \" o "d: \".
- Una sola barra invertida, por ejemplo, "\ directorio" o "\ archivo.txt". Esto también se conoce como ruta absoluta.
Si un nombre de archivo comienza solo con un designador de disco pero no con la barra invertida después de los dos puntos, se interpreta como una ruta relativa al directorio actual en la unidad con la letra especificada. Tenga en cuenta que el directorio actual puede ser o no el directorio raíz, dependiendo de lo que se configuró durante la operación de "cambio de directorio" más reciente en ese disco. Ejemplos de este formato son los siguientes:
- "C: tmp.txt" se refiere a un archivo llamado "tmp.txt" en el directorio actual de la unidad C.
- "C: tempdir \ tmp.txt" se refiere a un archivo en un subdirectorio del directorio actual en la unidad C.
[...]
Pregunta antigua, pero una respuesta más aplicable. Si necesita asegurarse de que el volumen esté incluido en una ruta local, puede usar System.IO.Path.GetFullPath () así:
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
accede al sistema de archivos y puede generar una serie de posibles excepciones. Vea mi respuesta ( stackoverflow.com/a/35046453/704808 ) para ver una alternativa que aún garantiza una ruta completa.
Basándose en la respuesta de weir : esto no arroja rutas no válidas, sino que también devuelve false
rutas como "C:", "C: dirname" y "\ ruta".
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
}
Tenga en cuenta que esto arroja resultados diferentes en Windows y Linux, por ejemplo, "/ ruta" es absoluto en Linux, pero no en Windows.
Prueba de unidad:
[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 si una ruta está completamente calificada (MSDN) :
public static bool IsPathFullyQualified(string path)
{
var root = Path.GetPathRoot(path);
return root.StartsWith(@"\\") || root.EndsWith(@"\");
}
Es un poco más simple de lo que ya se ha propuesto y todavía devuelve falso para rutas relativas a unidades como C:foo
. Su lógica se basa directamente en la definición de MSDN de "totalmente calificado", y no he encontrado ningún ejemplo en el que se comporte mal.
Curiosamente, sin embargo, .NET Core 2.1 parece tener un nuevo método Path.IsPathFullyQualified
que utiliza un método interno PathInternal.IsPartiallyQualified
(la ubicación del enlace es precisa a partir de 2018-04-17).
Para la posteridad y una mejor autocontención de esta publicación, aquí está la implementación de esta última como referencia:
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 es la solución que uso
public static bool IsFullPath(string path)
{
try
{
return Path.GetFullPath(path) == path;
}
catch
{
return false;
}
}
Funciona de la siguiente manera:
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
oC:\foo\.\.\.
Llame a la siguiente función:
Path.IsPathFullyQualified(@"c:\foo")
Documento de MSDN: Método Path.IsPathFullyQualified
La cita útil del documento de MSDN sigue:
Este método maneja rutas que usan el separador de directorio alternativo. Es un error frecuente asumir que las rutas enraizadas ( IsPathRooted (String) ) no son relativas. Por ejemplo, "C: a" es relativo a la unidad, es decir, se resuelve en el directorio actual de C: (arraigado, pero relativo). "C: \ a" está enraizado y no es relativo, es decir, el directorio actual no se usa para modificar la ruta.
No estoy realmente seguro de lo que quiere decir con ruta completa (aunque asumiendo del ejemplo que quiere decir no relativo desde la raíz en adelante), bueno, puede usar la clase Path para ayudarlo a trabajar con rutas físicas del sistema de archivos, que deberían cubrir usted para la mayoría de las eventualidades.