Come trovo la directory principale in C #?


86

Uso questo codice per trovare la directory di debug

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

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

Come posso trovare la cartella principale come mostrato di seguito?

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


16
Perché le persone usano sempre ToString () sulle stringhe?
Hogan

2
@ Hogan, nel caso in cui la proprietà cambi? : D
musefan

Risposte:


128

È possibile utilizzare System.IO.Directory.GetParent()per recuperare la directory principale di una determinata directory.


23
se la directory ha barre finali, devi chiamare GetParent due volte
northben

3
Questo sembra funzionare su percorsi relativi (sorpresa felice), ma non ha modo di recuperare il risultato (sorpresa infelice).
Adam

15
Puoi evitare il problema delle barre finali utilizzando invece DirectoryInfo.Parent. es new System.IO.DirectoryInfo("c:/path/to/somewhere//").Parent. @northben
mcNux

47
string parent = System.IO.Directory.GetParent(str_directory).FullName;

Vedi BOL


35

Se aggiungi ..\..al percorso esistente, il sistema operativo esplorerà correttamente la cartella principale.

Questo dovrebbe fare il lavoro:

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

Se esplori quel percorso, esplorerai la directory dei genitori.


1
Sembrava carino, ma sfortunatamente dà C: \ Users \ Masoud \ Documents \ Visual Studio 2008 \ Projects \ MyProj \ MyProj \ bin \ Debug \ .. \ ..
StuartQ

Sì e se sfogli quel percorso, esplorerai la directory genitore-genitore.
Pierre-Alain Vigeant

Giusto punto, rimuoverò il voto negativo, anche se dovrò modificare nel tuo commento per restituire il punto.
StuartQ

3
Il risultato di "Path.Combine" può essere passato attraverso "Path.GetFullPath" per ripulirlo. Ovvero per arrivare a "C: \ Users \ Masoud \ Documents \ Visual Studio 2008 \ Projects \ MyProj \ MyProj"
Konstantin

1
Questo è il modo migliore per salire di diversi livelli nell'albero delle directory
Trung Le

19

Ho scoperto che le varianti di System.IO.Path.Combine(myPath, "..")sono le più semplici e affidabili. Ancora di più se ciò che dice northben è vero, quel GetParent richiede una chiamata in più se c'è una barra finale. Questo, per me, è inaffidabile.

Path.Combine ti assicura di non sbagliare mai con le barre.

..si comporta esattamente come fa ovunque in Windows. Puoi aggiungere qualsiasi numero di file\.. a un percorso in cmd o explorer e si comporterà esattamente come descritto di seguito.

Alcuni ..comportamenti di base :

  1. Se c'è un nome di file, ..lo taglierà:

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

  1. Se il percorso è una directory, ..salirà di un livello:

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

  1. ..\.. segue le stesse regole, due volte di seguito:

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

  1. E questo ha lo stesso identico effetto:

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


1
Sono d'accordo che questo metodo ha il vantaggio di funzionare indipendentemente dal fatto che il percorso abbia o meno una barra rovesciata finale. E nelle situazioni in cui desideri un percorso semplice senza i punti in esso, puoi applicare Path.GetFullPath (() al risultato.
RenniePet

1
Due anni dopo e mi ritrovo di nuovo qui. Tieni presente che Path.GetFullPath (() normalmente restituisce un percorso senza alcuna barra rovesciata finale, ma quando arrivi alla directory principale, ad esempio "E: \", c'è una barra rovesciata.
RenniePet

Questo non funziona, né con .NET 4.7 né .NET Core 2.1: Path.Combine(@"D:\Grandparent\Parent\Child.txt", @"..")=D:\Grandparent\Parent\Child.txt\..
Métoule

Questo non tronca il nome del file per me, almeno su MacOS tramite Unity.
supergra

@ Métoule @supergra Vedo la confusione. Path.Combinenon tronca la stringa stessa. Il percorso , una volta utilizzato per accedere al file system, ha l'effetto desiderato. Tuttavia, sono d'accordo sul fatto che questo non sia ottimale. Vedi la mia risposta più recente in questa pagina per un approccio che modifica la stringa invece di aver bisogno del file system per risolvere il percorso.
Timo

11

Per ottenere una directory "nonni", chiama Directory.GetParent () due volte:

var gparent = Directory.GetParent(Directory.GetParent(str_directory).ToString());

1
var gparent = Directory.GetParent(str_directory).Parent; // Cleaner?
JohnB

8

Directory.GetParentè probabilmente una risposta migliore, ma per completezza c'è un metodo diverso che prende stringa e restituisce stringa: Path.GetDirectoryName.

string parent = System.IO.Path.GetDirectoryName(str_directory);

1
Intendiamoci Path.GetDirectoryName non funziona bene con i percorsi relativi .. Directory.GetParent lo fa.
nawfal

6

Come questo:

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

In bocca al lupo!


1
myDirectory.Parent.ToString () restituisce il nome della sottocartella, non il percorso completo, esattamente quello che stavo cercando. Inoltre, invece di eseguire Directory.GetParent (Directory.GetParent (str_directory) .ToString ()); come mostrato sopra, semplicemente usando myDirectory.parent.parent.ToString () si ottiene il 'nonno'.
Weihui Guo

1
Trovo che questo metodo sia il migliore perché gestisce il caso in cui il percorso della directory abbia barre finali. Considerando che se usi Directory.GetParent (), devi chiamarlo due volte per rimuovere le barre e quindi ottenere il genitore effettivo.
Magnus


3

Per evitare problemi con il trailing \, chiamalo in questo modo:

  string ParentFolder =  Directory.GetParent( folder.Trim('\\')).FullName;

1
È possibile utilizzare TrimEndse si desidera rimuovere solo trailing `'s . I'm not sure if a leading `è significativo in altri sistemi operativi.
Walter Stabosz

2

Per ottenere la tua soluzione prova questo

string directory = System.IO.Directory.GetParent(System.IO.Directory.GetParent(Environment.CurrentDirectory).ToString()).ToString();

2

Questo è il modo più comune - dipende davvero da cosa stai facendo esattamente: (per spiegare, l'esempio seguente rimuoverà gli ultimi 10 caratteri che è ciò che hai richiesto, tuttavia se ci sono alcune regole aziendali che guidano la tua esigenza per trovare una posizione specifica dovresti usarli per recuperare la posizione della directory, non trovare la posizione di qualcos'altro e modificarla.)

// remove last 10 characters from a string
str_directory = str_directory.Substring(0,str_directory.Length-10);

Il tuo primo funziona solo se sai che gli ultimi caratteri sono esattamente \bin\Debug , senza che ` and no other path, so it's extraordinarily fragile. Your second doesn't work because Environment.CurrentDirectory` sia una stringa e le stringhe non hanno una Parentproprietà.
Joe White,

@ Joe, ho rimosso il 2 °. Ma penso che questa sia una risposta valida, se il percorso è sempre \ bin \ debug funzionerà. E come ho detto, l'OP dovrebbe davvero guardare a ciò che è il BR che determina la necessità della directory e utilizzare un approccio diverso (probabilmente userei una voce di configurazione, ma immagino che il BR e la struttura del programma.)
Hogan

Sebbene non sia perfetto e fragile, è l'unica soluzione che ha funzionato per me. Modifica suggerita: "str_directory.length" dovrebbe essere "str_directory.Length", la L minuscola non è accettabile.
OverMars

2

Nessuno ha fornito una soluzione che funzioni in modo incrociato. So che non è stato richiesto specificamente ma sto lavorando in un ambiente Linux in cui la maggior parte delle soluzioni (come al momento in cui lo posto) fornirebbe un errore.

I separatori di percorso hardcoding (così come altre cose) daranno un errore in tutto tranne che nei sistemi Windows.

Nella mia soluzione originale ho usato:

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

Tuttavia, dopo aver visto alcune delle risposte qui, l'ho adattato per essere:

string datapath = Directory.GetParent(Directory.GetParent(Directory.GetCurrentDirectory()).FullName).FullName; 

2

Poiché nient'altro che ho trovato aiuta a risolvere questo problema in un modo veramente normalizzato, ecco un'altra risposta.

Tieni presente che alcune risposte a domande simili tentano di utilizzare l'estensione Uri tipo, ma questo ha difficoltà anche con le barre finali rispetto alle barre finali.

La mia altra risposta in questa pagina funziona per le operazioni che mettono in funzione il file system, ma se vogliamo avere il percorso risolto in questo momento (ad esempio per motivi di confronto), senza passare attraverso il file system C:/Temp/..eC:/ sarebbe considerato diverso. Senza passare attraverso il file system, navigare in quel modo non ci fornisce un percorso normalizzato e adeguatamente comparabile.

Cosa possiamo fare?

Costruiremo sulla seguente scoperta:

Path.GetDirectoryName(path + "/") ?? ""ci darà in modo affidabile un percorso di directory senza una barra finale .

  • L'aggiunta di una barra (come string, non come char) tratterà un nullpercorso nello stesso modo in cui tratta "".
  • GetDirectoryName eviterà di scartare l'ultimo componente del percorso grazie alla barra aggiunta.
  • GetDirectoryName normalizzerà le barre e i punti di navigazione.
  • Ciò include la rimozione di eventuali barre finali.
  • Ciò include il collasso ..navigando verso l'alto.
  • GetDirectoryNametornerà nullper un percorso vuoto, su cui ci uniamo "".

Come lo usiamo?

Innanzitutto, normalizza il percorso di input :

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

Quindi, possiamo ottenere la directory padre e possiamo ripetere questa operazione un numero qualsiasi di volte per navigare più in alto:

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

Nota che non abbiamo mai toccato il file system. Nessuna parte del percorso deve esistere, come sarebbe se avessimo usato DirectoryInfo.


1

Non dovresti provare a farlo. Environment.CurrentDirectory fornisce il percorso della directory eseguibile. Ciò è coerente indipendentemente da dove si trova il file .exe. Non dovresti provare ad accedere a un file che si presume si trovi in ​​una posizione relativa all'indietro

Ti suggerirei di spostare qualsiasi risorsa a cui desideri accedere in una posizione locale. Di una directory di sistema (come AppData)


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

Se si deseleziona " bin\Debug\" nelle proprietà del progetto -> Crea -> Percorso di output, è possibile utilizzare semplicementeAppDomain.CurrentDomain.BaseDirectory

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.