¿Cómo encuentro el directorio principal en C #?

85

Utilizo este código para encontrar el directorio de depuración

public string str_directory = Environment.CurrentDirectory.ToString();

"C:\\Users\\Masoud\\Documents\\Visual Studio 2008\\Projects\\MyProj\\MyProj\\bin\\Debug"

¿Cómo puedo encontrar la carpeta principal como se muestra a continuación?

"C:\\Users\\Masoud\\Documents\\Visual Studio 2008\\Projects\\MyProj\\MyProj"

Masoud Abasian
fuente
15
¿Por qué la gente siempre usa ToString () en cadenas?
Hogan
1
@Hogan, en caso de que cambie la propiedad? : D
musefan

Respuestas:

126

Puede utilizar System.IO.Directory.GetParent()para recuperar el directorio principal de un directorio determinado.

Sylence
fuente
21
si el directorio tiene barras al final, debe llamar a GetParent dos veces
northben
2
Esto parece funcionar en rutas relativas (sorpresa feliz), pero luego no tiene forma de recuperar el resultado (sorpresa infeliz).
Adam
14
En su lugar, puede evitar el problema de las barras inclinadas utilizando DirectoryInfo.Parent. ej new System.IO.DirectoryInfo("c:/path/to/somewhere//").Parent. @northben
mcNux
46
string parent = System.IO.Directory.GetParent(str_directory).FullName;

Ver BOL

billinkc
fuente
35

Si agrega ..\..a su ruta existente, el sistema operativo examinará correctamente la carpeta principal.

Eso debería hacer el trabajo:

System.IO.Path.Combine("C:\\Users\\Masoud\\Documents\\Visual Studio 2008\\Projects\\MyProj\\MyProj\\bin\\Debug", @"..\..");

Si explora esa ruta, explorará el directorio de los abuelos.

Pierre-Alain Vigeant
fuente
1
Eso se veía bien, pero desafortunadamente da C: \ Users \ Masoud \ Documents \ Visual Studio 2008 \ Projects \ MyProj \ MyProj \ bin \ Debug \ .. \ ..
StuartQ
Sí, y si explora esa ruta, explorará el directorio padre-padre.
Pierre-Alain Vigeant
Buen punto, eliminaré el voto negativo, aunque tendré que editar tu comentario para devolver el punto.
StuartQ
3
El resultado de "Path.Combine" se puede pasar a través de "Path.GetFullPath" para limpiarlo. Eso es para llegar a "C: \ Users \ Masoud \ Documents \ Visual Studio 2008 \ Projects \ MyProj \ MyProj"
Konstantin
1
Esta es la mejor manera de subir varios niveles en el árbol de directorios
Trung Le
18

He descubierto que las variantes de System.IO.Path.Combine(myPath, "..")son las más fáciles y fiables. Más aún si lo que dice Northben es cierto, GetParent requiere una llamada adicional si hay una barra al final. Eso, para mí, no es confiable.

Path.Combine se asegura de que nunca te equivoques con las barras.

..se comporta exactamente como lo hace en cualquier otro lugar de Windows. Puede agregar cualquier número de \..a una ruta en cmd o explorer y se comportará exactamente como describo a continuación.

Algún ..comportamiento básico :

  1. Si hay un nombre de archivo, ..lo cortará:

Path.Combine(@"D:\Grandparent\Parent\Child.txt", "..") => D:\Grandparent\Parent\

  1. Si la ruta es un directorio, ..subirá un nivel:

Path.Combine(@"D:\Grandparent\Parent\", "..") => D:\Grandparent\

  1. ..\.. sigue las mismas reglas, dos veces seguidas:

Path.Combine(@"D:\Grandparent\Parent\Child.txt", @"..\..")=> D:\Grandparent\ Path.Combine(@"D:\Grandparent\Parent\", @"..\..")=>D:\

  1. Y esto tiene exactamente el mismo efecto:

Path.Combine(@"D:\Grandparent\Parent\Child.txt", "..", "..")=> D:\Grandparent\ Path.Combine(@"D:\Grandparent\Parent\", "..", "..")=>D:\

Timo
fuente
1
Estoy de acuerdo en que este método tiene la ventaja de funcionar independientemente de que la ruta tenga o no una barra diagonal inversa. Y en situaciones en las que desee una ruta simple sin los puntos, puede aplicar Path.GetFullPath (() al resultado.
RenniePet
1
Dos años después, me encuentro de nuevo aquí. Tenga en cuenta que Path.GetFullPath (() normalmente devuelve una ruta sin ninguna barra invertida al final, pero cuando llega al directorio raíz, por ejemplo, "E: \", entonces hay una barra invertida.
RenniePet
Esto no funciona, ni con .NET 4.7 ni .NET Core 2.1: Path.Combine(@"D:\Grandparent\Parent\Child.txt", @"..")=D:\Grandparent\Parent\Child.txt\..
Métoule
Esto no trunca el nombre del archivo para mí, al menos en MacOS a través de Unity.
supergra
@ Métoule @supergra Veo la confusión. Path.Combineno trunca la cadena en sí. La ruta , una vez utilizada para acceder al sistema de archivos, tiene el efecto deseado. Sin embargo, estoy de acuerdo en que esto no es óptimo. Vea mi respuesta más reciente en esta página para conocer un enfoque que modifica la cadena en lugar de necesitar el sistema de archivos para resolver la ruta.
Timo
11

Para obtener un directorio de 'abuelos', llame a Directory.GetParent () dos veces:

var gparent = Directory.GetParent(Directory.GetParent(str_directory).ToString());
Jay Riggs
fuente
1
var gparent = Directory.GetParent(str_directory).Parent; // Cleaner?
JohnB
8

Directory.GetParentes probablemente una respuesta mejor, pero por lo completo que hay un método diferente que tiene cadena y devuelve la cadena: Path.GetDirectoryName.

string parent = System.IO.Path.GetDirectoryName(str_directory);
Carl Walsh
fuente
1
Eso sí, Path.GetDirectoryName no funciona bien con rutas relativas ... Directory.GetParent sí.
nawfal
6

Me gusta esto:

System.IO.DirectoryInfo myDirectory = new DirectoryInfo(Environment.CurrentDirectory);
string parentDirectory = myDirectory.Parent.FullName;

¡Buena suerte!

Michael Ames
fuente
1
myDirectory.Parent.ToString () devuelve el nombre de la subcarpeta, no la ruta completa, exactamente lo que estaba buscando. Además, en lugar de hacer Directory.GetParent (Directory.GetParent (str_directory) .ToString ()); como se muestra arriba, simplemente usando myDirectory.parent.parent.ToString () obtiene el 'abuelo'.
Weihui Guo
1
Encuentro que este método es el mejor porque maneja el caso en el que la ruta del directorio tiene barras inclinadas. Mientras que si usa Directory.GetParent (), debe llamarlo dos veces para eliminar las barras y luego obtener el padre real.
Magnus
3

Para evitar problemas con el seguimiento de \, llámelo de esta manera:

  string ParentFolder =  Directory.GetParent( folder.Trim('\\')).FullName;
ANUNCIO
fuente
1
Puede usarlo TrimEndsi solo desea eliminar el final `'s . I'm not sure if a leading `es significativo en otros sistemas operativos.
Walter Stabosz
2

Para obtener tu solución, prueba esto

string directory = System.IO.Directory.GetParent(System.IO.Directory.GetParent(Environment.CurrentDirectory).ToString()).ToString();
Siby Sunny
fuente
2

Esta es la forma más común, realmente depende de lo que esté haciendo exactamente: (Para explicar, el ejemplo a continuación eliminará los últimos 10 caracteres, que es lo que solicitó, sin embargo, si hay algunas reglas comerciales que impulsan su necesidad para encontrar una ubicación específica, debe usarlos para recuperar la ubicación del directorio, no encontrar la ubicación de otra cosa y modificarla).

// remove last 10 characters from a string
str_directory = str_directory.Substring(0,str_directory.Length-10);
Hogan
fuente
El primero solo funciona si sabe que los últimos caracteres son exactamente \bin\Debug , sin ` and no other path, so it's extraordinarily fragile. Your second doesn't work because Environment.CurrentDirectory` final es una cadena, y las cadenas no tienen una Parentpropiedad.
Joe White
@Joe, eliminé el segundo. Pero creo que esta es una respuesta válida, si la ruta es siempre \ bin \ debug, funcionará. Y como dije, el OP debería realmente mirar qué es el BR que impulsa la necesidad del directorio y usar un enfoque diferente (probablemente usaría una entrada de configuración, pero supongo que el BR y la estructura del programa)
Hogan
Aunque no es perfecto y frágil, es la única solución que funcionó para mí. Edición sugerida: "str_directory.length" debe ser "str_directory.Length", la L minúscula no es aceptable.
OverMars
2

Nadie ha proporcionado una solución que funcione de forma cruzada. Sé que no se preguntó específicamente, pero estoy trabajando en un entorno Linux donde la mayoría de las soluciones (como en el momento en que publico esto) proporcionarían un error.

Los separadores de ruta de codificación rígida (así como otras cosas) darán un error en cualquier cosa menos en los sistemas Windows.

En mi solución original usé:

char filesep = Path.DirectorySeparatorChar;
string datapath = $"..{filesep}..{filesep}";

Sin embargo, después de ver algunas de las respuestas aquí, lo ajusté para que sea:

string datapath = Directory.GetParent(Directory.GetParent(Directory.GetCurrentDirectory()).FullName).FullName; 
Madivad
fuente
2

Dado que nada más que he encontrado ayuda a resolver esto de una manera verdaderamente normalizada, aquí hay otra respuesta.

Tenga en cuenta que algunas respuestas a preguntas similares intentan usar el Uritipo, pero eso tiene dificultades con las barras diagonales finales frente a las barras inclinadas no.

Mi otra respuesta en esta página funciona para las operaciones que ponen el sistema de archivos de trabajo, pero si queremos tener el camino resuelto en este momento (por ejemplo, por razones de comparación), sin pasar por el sistema de archivos, C:/Temp/..y C:/sería considerado diferente. Sin pasar por el sistema de archivos, navegar de esa manera no nos proporciona una ruta normalizada y adecuadamente comparable.

¿Qué podemos hacer?

Nos basaremos en el siguiente descubrimiento:

Path.GetDirectoryName(path + "/") ?? ""nos dará de manera confiable una ruta de directorio sin una barra al final .

  • Agregar una barra (como string, no como char) tratará una nullruta de la misma manera que trata "".
  • GetDirectoryName se abstendrá de descartar el último componente de la ruta gracias a la barra inclinada agregada.
  • GetDirectoryName normalizará barras y puntos de navegación.
  • Esto incluye la eliminación de las barras diagonales finales.
  • Esto incluye colapsar ..navegando hacia arriba.
  • GetDirectoryNamevolverá nullpor un camino vacío, al que nos fusionamos "".

¿Cómo usamos esto?

Primero, normalice la ruta de entrada :

dirPath = Path.GetDirectoryName(dirPath + "/") ?? "";

Luego, podemos obtener el directorio principal y podemos repetir esta operación cualquier cantidad de veces para navegar más hacia arriba:

// This is reliable if path results from this or the previous operation
path = Path.GetDirectoryName(path);

Tenga en cuenta que nunca hemos tocado el sistema de archivos. No es necesario que exista ninguna parte del camino, como lo haría si lo hubiéramos utilizado DirectoryInfo.

Timo
fuente
1

No deberías intentar hacer eso. Environment.CurrentDirectory le proporciona la ruta del directorio ejecutable. Esto es coherente independientemente de dónde esté el archivo .exe. No debe intentar acceder a un archivo que se supone que está en una ubicación relativa hacia atrás

Le sugiero que mueva cualquier recurso al que desee acceder a una ubicación local. De un directorio del sistema (como AppData)

musefan
fuente
1
IO.Path.GetFullPath(@"..\..")

Si borra " bin\Debug\" en las propiedades del proyecto -> Generar -> Ruta de salida, entonces puede usarAppDomain.CurrentDomain.BaseDirectory

Slai
fuente