Wie finde ich das übergeordnete Verzeichnis in C #?

86

Ich benutze diesen Code, um das Debug-Verzeichnis zu finden

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

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

Wie finde ich den übergeordneten Ordner wie unten gezeigt?

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

Masoud Abasian
quelle
15
Warum verwenden Leute ToString () immer für Strings?
Hogan
1
@Hogan, falls sich die Eigenschaft ändert? : D
Musefan

Antworten:

128

Sie können System.IO.Directory.GetParent()das übergeordnete Verzeichnis eines bestimmten Verzeichnisses abrufen.

Sylence
quelle
23
Wenn das Verzeichnis nachgestellte Schrägstriche enthält, müssen Sie GetParent zweimal
aufrufen
3
Dies scheint auf relativen Pfaden zu funktionieren (glückliche Überraschung), hat dann aber keine Möglichkeit für Sie, das Ergebnis zurückzubekommen (unglückliche Überraschung).
Adam
15
Sie können das Problem der abschließenden Schrägstriche vermeiden, indem Sie stattdessen verwenden DirectoryInfo.Parent. zB new System.IO.DirectoryInfo("c:/path/to/somewhere//").Parent. @northben
mcNux
47
string parent = System.IO.Directory.GetParent(str_directory).FullName;

Siehe BOL

billinkc
quelle
35

Wenn Sie ..\..an Ihren vorhandenen Pfad anhängen , durchsucht das Betriebssystem den übergeordneten Ordner korrekt.

Das sollte den Job machen:

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

Wenn Sie diesen Pfad durchsuchen, durchsuchen Sie das übergeordnete Verzeichnis.

Pierre-Alain Vigeant
quelle
1
Das sah gut aus, gibt aber leider C: \ Benutzer \ Masoud \ Dokumente \ Visual Studio 2008 \ Projekte \ MyProj \ MyProj \ bin \ Debug \ .. \ ..
StuartQ
Ja, und wenn Sie diesen Pfad durchsuchen, durchsuchen Sie das Eltern-Eltern-Verzeichnis.
Pierre-Alain Vigeant
Fairer Punkt, ich werde die Abwertung entfernen, obwohl ich Ihren Kommentar bearbeiten muss, um den Punkt zurückzugeben.
StuartQ
3
Das Ergebnis von "Path.Combine" kann über "Path.GetFullPath" übergeben werden, um es zu bereinigen. Das ist zu "C: \ Benutzer \ Masoud \ Dokumente \ Visual Studio 2008 \ Projekte \ MyProj \ MyProj"
Konstantin
1
Dies ist der beste Weg, um mehrere Ebenen im Verzeichnisbaum zu erreichen
Trung Le
18

Ich habe festgestellt, dass Varianten von System.IO.Path.Combine(myPath, "..")am einfachsten und zuverlässigsten sind. Umso mehr, wenn das, was Northben sagt, wahr ist, erfordert GetParent einen zusätzlichen Aufruf, wenn ein abschließender Schrägstrich vorliegt. Das ist für mich unzuverlässig.

Path.Combine stellt sicher, dass Sie mit Schrägstrichen nichts falsch machen.

..verhält sich genauso wie überall sonst in Windows. Sie können \..einem Pfad in cmd oder explorer eine beliebige Anzahl hinzufügen, und er verhält sich genau so, wie ich es unten beschreibe.

Einige grundlegende ..Verhaltensweisen:

  1. Wenn es einen Dateinamen gibt, ..wird dieser abgeschnitten:

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

  1. Wenn der Pfad ein Verzeichnis ist, ..wird eine Ebene nach oben verschoben:

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

  1. ..\.. folgt zweimal hintereinander den gleichen Regeln:

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

  1. Und das hat genau den gleichen Effekt:

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

Timo
quelle
1
Ich bin damit einverstanden, dass diese Methode den Vorteil hat, dass unabhängig davon gearbeitet wird, ob der Pfad einen nachgestellten Backslash aufweist oder nicht. Und in Situationen, in denen Sie einen einfachen Pfad ohne die darin enthaltenen Punkte wünschen, können Sie Path.GetFullPath (() auf das Ergebnis
anwenden
1
Zwei Jahre später bin ich wieder hier. Beachten Sie, dass Path.GetFullPath (() normalerweise einen Pfad ohne nachgestellten Backslash zurückgibt. Wenn Sie jedoch zum Stammverzeichnis gelangen, z. B. "E: \", gibt es einen Backslash.
RenniePet
Dies funktioniert nicht, weder mit .NET 4.7 noch .NET Core 2.1: Path.Combine(@"D:\Grandparent\Parent\Child.txt", @"..")=D:\Grandparent\Parent\Child.txt\..
Métoule
Dies schneidet den Dateinamen für mich nicht ab, zumindest unter MacOS über Unity.
Supergra
@ Métoule @ supergra Ich sehe die Verwirrung. Path.Combineschneidet die Zeichenfolge selbst nicht ab. Der Pfad , der einmal für den Zugriff auf das Dateisystem verwendet wurde, hat den beabsichtigten Effekt. Ich stimme jedoch zu, dass dies nicht optimal ist. In meiner neueren Antwort auf dieser Seite finden Sie einen Ansatz, mit dem die Zeichenfolge geändert wird, anstatt dass das Dateisystem zum Auflösen des Pfads erforderlich ist.
Timo
11

Rufen Sie Directory.GetParent () zweimal auf, um ein Verzeichnis für Großeltern zu erhalten :

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

Directory.GetParentist wahrscheinlich eine bessere Antwort, aber der Vollständigkeit halber gibt es eine andere Methode, die Zeichenfolge verwendet und Zeichenfolge zurückgibt : Path.GetDirectoryName.

string parent = System.IO.Path.GetDirectoryName(str_directory);
Carl Walsh
quelle
1
Wohlgemerkt, Path.GetDirectoryName funktioniert nicht gut mit relativen Pfaden. Directory.GetParent funktioniert nicht.
Nawfal
6

So was:

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

Viel Glück!

Michael Ames
quelle
1
myDirectory.Parent.ToString () gibt den Namen des Unterordners zurück, nicht den vollständigen Pfad, genau das, wonach ich gesucht habe. Anstatt Directory.GetParent (Directory.GetParent (str_directory) .ToString ()) auszuführen; Wie oben gezeigt, wird durch einfaches Verwenden von myDirectory.parent.parent.ToString () der 'Großelternteil' abgerufen.
Weihui Guo
1
Ich finde diese Methode am besten, weil sie den Fall behandelt, in dem Ihr Verzeichnispfad nachgestellte Schrägstriche aufweist. Wenn Sie Directory.GetParent () verwenden, müssen Sie es zweimal aufrufen, um die Schrägstriche zu entfernen und dann das eigentliche übergeordnete Element abzurufen.
Magnus
5

Vielleicht möchten Sie in die DirectoryInfo. ParentEigentum.

Ravuya
quelle
3

Um Probleme mit Trailing \ zu vermeiden, nennen Sie es folgendermaßen:

  string ParentFolder =  Directory.GetParent( folder.Trim('\\')).FullName;
ANZEIGE
quelle
1
Sie können verwenden, TrimEndwenn Sie nur das abschließende `'s . I'm not sure if a leading ` entfernen möchten, was in anderen Betriebssystemen von Bedeutung ist.
Walter Stabosz
2

Versuchen Sie dies, um Ihre Lösung zu erhalten

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

Dies ist der häufigste Weg - es hängt wirklich davon ab, was Sie genau tun: (Um dies zu erklären, werden im folgenden Beispiel die letzten 10 Zeichen entfernt, nach denen Sie gefragt haben. Wenn es jedoch einige Geschäftsregeln gibt, die Ihre Anforderungen erfüllen Um einen bestimmten Speicherort zu finden, sollten Sie diese verwenden, um den Verzeichnisspeicherort abzurufen, nicht den Speicherort von etwas anderem zu finden und ihn zu ändern.)

// remove last 10 characters from a string
str_directory = str_directory.Substring(0,str_directory.Length-10);
Hogan
quelle
Ihr erstes Zeichen funktioniert nur, wenn Sie wissen, dass die letzten Zeichen genau \bin\Debug und ohne nachgestellte ` and no other path, so it's extraordinarily fragile. Your second doesn't work because Umgebung sind. CurrentDirectory` ist eine Zeichenfolge, und Zeichenfolgen haben keine ParentEigenschaft.
Joe White
@ Joe, ich habe den 2. entfernt. Aber ich denke, dies ist eine gültige Antwort. Wenn der Pfad immer \ bin \ debug lautet, funktioniert er. Und wie gesagt, das OP sollte sich wirklich ansehen, was der BR ist, der die Notwendigkeit für das Verzeichnis antreibt, und einen anderen Ansatz verwenden (ich würde wahrscheinlich einen Konfigurationseintrag verwenden, aber ich vermute den BR und die Programmstruktur.)
Hogan
Obwohl es nicht perfekt und zerbrechlich ist, ist es die einzige Lösung, die für mich funktioniert hat. Vorgeschlagene Bearbeitung: "str_directory.length" sollte "str_directory.Length" sein, Kleinbuchstaben L sind nicht akzeptabel.
OverMars
2

Niemand hat eine Lösung bereitgestellt, die formübergreifend funktionieren würde. Ich weiß, dass es nicht speziell gefragt wurde, aber ich arbeite in einer Linux-Umgebung, in der die meisten Lösungen (wie zum Zeitpunkt der Veröffentlichung) einen Fehler liefern würden.

Das Hardcodieren von Pfadtrennzeichen (und anderen Dingen) führt bei allen anderen als Windows-Systemen zu einem Fehler.

In meiner ursprünglichen Lösung habe ich verwendet:

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

Nachdem ich jedoch einige der Antworten hier gesehen hatte, passte ich sie an:

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

Da nichts anderes, was ich gefunden habe, hilft, dies auf wirklich normalisierte Weise zu lösen, ist hier eine andere Antwort.

Beachten Sie, dass einige Antworten auf ähnliche Fragen versuchen, das zu verwenden Uri Typ zu verwenden, dies jedoch mit abschließenden Schrägstrichen keinen abschließenden Schrägstrichen zu kämpfen hat.

Meine andere Antwort auf dieser Seite funktioniert für Vorgänge, bei denen das Dateisystem funktioniert, aber wenn wir den aufgelösten Pfad jetzt haben möchten (z. B. aus Vergleichsgründen), ohne das Dateisystem zu durchlaufen, C:/Temp/..undC:/ würde anders betrachtet werden. Ohne das Dateisystem zu durchlaufen, bietet uns die Navigation auf diese Weise keinen normalisierten, ordnungsgemäß vergleichbaren Pfad.

Was können wir tun?

Wir werden auf der folgenden Entdeckung aufbauen:

Path.GetDirectoryName(path + "/") ?? ""wird zuverlässig uns einen Verzeichnispfad geben ohne einen Schrägstrich .

  • Durch Hinzufügen eines Schrägstrichs (als string, nicht als char) wird ein nullPfad genauso behandelt, wie er behandelt wird"" .
  • GetDirectoryName wird die letzte Pfadkomponente dank des hinzugefügten Schrägstrichs nicht verwerfen.
  • GetDirectoryName normalisiert Schrägstriche und Navigationspunkte.
  • Dies schließt das Entfernen von nachgestellten Schrägstrichen ein.
  • Dies schließt das Reduzieren ..durch Navigieren nach oben ein.
  • GetDirectoryNamewird nullfür einen leeren Weg zurückkehren, zu dem wir verschmelzen "".

Wie nutzen wir das?

Zuerst Normalisieren der Eingabepfad :

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

Dann können wir das übergeordnete Verzeichnis abrufen und diesen Vorgang beliebig oft wiederholen, um weiter nach oben zu navigieren:

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

Beachten Sie, dass wir das Dateisystem noch nie berührt haben. Kein Teil des Pfades muss existieren, wie es wäre, wenn wir es benutzt hätten DirectoryInfo.

Timo
quelle
1

Sie sollten nicht versuchen, das zu tun. Environment.CurrentDirectory gibt Ihnen den Pfad des ausführbaren Verzeichnisses an. Dies ist konsistent, unabhängig davon, wo sich die EXE-Datei befindet. Sie sollten nicht versuchen, auf eine Datei zuzugreifen, von der angenommen wird, dass sie sich an einem relativen Speicherort befindet

Ich würde vorschlagen, dass Sie die Ressource, auf die Sie zugreifen möchten, an einen lokalen Ort verschieben. Von einem Systemverzeichnis (wie AppData)

Musefan
quelle
1
IO.Path.GetFullPath(@"..\..")

Wenn Sie das " bin\Debug\" in den Projekteigenschaften -> Erstellen -> Ausgabepfad löschen , können Sie es einfach verwendenAppDomain.CurrentDomain.BaseDirectory

Slai
quelle