C # 'da üst dizini nasıl bulurum?


86

Bu kodu hata ayıklama dizinini bulmak için kullanıyorum

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

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

Aşağıda gösterildiği gibi ana klasörü nasıl bulabilirim?

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


16
İnsanlar neden dizelerde her zaman ToString () kullanıyor?
Hogan

2
@Hogan, mülkiyetin değişmesi durumunda? : D
musefan

Yanıtlar:


128

System.IO.Directory.GetParent()Belirli bir dizinin üst dizinini almak için kullanabilirsiniz .


23
dizinde eğik çizgiler varsa, GetParent'ı iki kez aramanız gerekir
northben

3
Bu, göreceli yollarda işe yarıyor gibi görünüyor (mutlu sürpriz), ancak o zaman sonucu geri almanın bir yolu yok (mutsuz sürpriz).
Adam

15
Bunun yerine kullanarak sondaki eğik çizgi sorununu önleyebilirsiniz DirectoryInfo.Parent. ör new System.IO.DirectoryInfo("c:/path/to/somewhere//").Parent. @northben
mcNux


35

..\..Mevcut yolunuza eklerseniz , işletim sistemi büyük ebeveyn klasörüne doğru şekilde göz atacaktır.

Bu işi yapmalı:

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

Bu yola göz atarsanız, büyük ebeveyn dizinine göz atarsınız.


1
Bu güzel görünüyordu, ancak ne yazık ki C: \ Users \ Masoud \ Documents \ Visual Studio 2008 \ Projects \ MyProj \ MyProj \ bin \ Debug \ .. \ ..
StuartQ

Evet ve bu yola göz atarsanız, üst-üst dizine göz atarsınız.
Pierre-Alain Vigeant

Doğru nokta, olumsuz oyu kaldıracağım, ancak noktayı geri vermek için yorumunuzu düzenlemem gerekecek.
StuartQ

3
"Path.Combine" işleminin sonucu, temizlenmesi için "Path.GetFullPath" içinden geçirilebilir. Bu, "C: \ Users \ Masoud \ Documents \ Visual Studio 2008 \ Projects \ MyProj \ MyProj" konumuna ulaşmak içindir
Konstantin

1
Bu, dizin ağacında birkaç seviye yukarı çıkmanın en iyi yoludur
Trung Le

19

System.IO.Path.Combine(myPath, "..")En kolay ve en güvenilir varyantlarını buldum . Dahası, northben'in söylediği doğruysa, GetParent'ın sonda bir eğik çizgi varsa fazladan bir çağrı gerektirmesi. Bu benim için güvenilmez.

Path.Combine eğik çizgilerle asla hata yapmamanızı sağlar.

..Windows'ta her yerde olduğu gibi davranır. \..Cmd veya explorer'daki bir yola herhangi bir sayıda ekleyebilirsiniz ve tam olarak aşağıda tarif ettiğim gibi davranacaktır.

Bazı temel ..davranışlar:

  1. Bir dosya adı varsa, ..onu keser:

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

  1. Yol bir dizin ise, ..bir seviye yukarı çıkacaktır:

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

  1. ..\.. arka arkaya iki kez aynı kuralları takip eder:

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

  1. Ve bu aynı etkiye sahiptir:

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


1
Yolun sonunda ters eğik çizgi olsa da olmasa da bu yöntemin çalışma avantajına sahip olduğunu kabul ediyorum. Ve içinde noktalar olmadan basit bir yol istediğiniz durumlarda, sonuca Path.GetFullPath (() uygulayabilirsiniz.
RenniePet

1
İki yıl sonra kendimi tekrar burada buluyorum. Path.GetFullPath (() normalde herhangi ters eğik çizgi olmadan bir yol döndürdüğünü unutmayın, ancak önce, örneğin kök dizinine "E: \" kalk, o zaman bir ters eğik çizgi yoktur.
RenniePet

Bu ne .NET 4.7 ne de .NET Core 2.1 ile çalışmıyor: Path.Combine(@"D:\Grandparent\Parent\Child.txt", @"..")=D:\Grandparent\Parent\Child.txt\..
Métoule

Bu benim için dosya adını kısaltmıyor, en azından Unity aracılığıyla MacOS'ta.
supergra

@ Métoule @supergra Karışıklığı görüyorum. Path.Combinedizenin kendisini kesmez. Dosya sistemine erişmek için kullanılan yol , amaçlanan etkiye sahiptir. Ancak bunun yetersiz olduğunu kabul ediyorum. Yolu çözmek için dosya sistemine ihtiyaç duymak yerine dizeyi değiştiren bir yaklaşım için bu sayfadaki daha yeni cevabıma bakın .
Timo

11

Bir 'büyükbaba' dizini almak için Directory.GetParent () öğesini iki kez çağırın :

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

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

8

Directory.GetParentMuhtemelen daha iyi bir cevaptır, ancak şeyiyle dize ve döner dize alır, farklı bir yöntem var: Path.GetDirectoryName.

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

1
Unutmayın Path.GetDirectoryName göreceli yollarla iyi çalışmaz .. Directory.GetParent yapar.
nawfal

6

Bunun gibi:

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

İyi şanslar!


1
myDirectory.Parent.ToString () tam yolu değil, tam olarak aradığım alt klasörün adını döndürür. Ayrıca Directory.GetParent (Directory.GetParent (str_directory) .ToString ()) yapmak yerine; Yukarıda gösterildiği gibi, sadece myDirectory.parent.parent.ToString () kullanmak 'büyükbaba' olur.
Weihui Guo

1
Bu yöntemi en iyi buluyorum çünkü dizin yolunuzun sonunda eğik çizgilerin olduğu durumu ele alıyor. Oysa Directory.GetParent () kullanıyorsanız, eğik çizgileri kaldırmak ve ardından asıl ana öğeyi almak için onu iki kez çağırmanız gerekir.
Magnus


3

Sonda ile ilgili sorunları önlemek için \ şu şekilde adlandırın:

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

1
Sen kullanabilirsiniz TrimEndyalnızca sondaki kaldırmak istiyorsanız `'s . I'm not sure if a leading `diğer işletim sistemleri de önemlidir.
Walter Stabosz

2

Çözümünüzü almak için bunu deneyin

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

2

Bu en yaygın yoldur - gerçekten tam olarak ne yaptığınıza bağlıdır: (Açıklamak gerekirse, aşağıdaki örnek, istediğiniz son 10 karakteri kaldıracaktır, ancak ihtiyacınıza neden olan bazı iş kuralları varsa belirli bir konumu bulmak için, bunları dizin konumunu almak için kullanmalısınız, başka bir şeyin yerini bulup değiştirmemelisiniz.)

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

İlkiniz yalnızca, son karakterlerin tam olarak \bin\Debug , sondaki ` and no other path, so it's extraordinarily fragile. Your second doesn't work because Environment.CurrentDirectory` bir dizge olduğunu ve dizelerin bir Parentözelliği olmadığını biliyorsanız çalışır .
Joe White

@Joe, 2.'yi kaldırdım. Ama bunun geçerli bir cevap olduğunu düşünüyorum, eğer yol her zaman \ bin \ debug ise işe yarayacaktır. Ve dediğim gibi OP, dizin ihtiyacını tetikleyen BR'nin ne olduğuna gerçekten bakmalı ve farklı bir yaklaşım kullanmalı (muhtemelen bir yapılandırma girişi kullanırım, ancak BR ve program yapısında tahmin ediyorum.)
Hogan

Kusursuz ve kırılgan olmasa da, benim için işe yarayan tek çözüm bu. Önerilen düzenleme: "str_directory.length" "str_directory.Length" olmalıdır, küçük harf L kabul edilemez.
OverMars

2

Hiç kimse çapraz formda çalışacak bir çözüm sağlamadı. Özel olarak sorulmadığını biliyorum, ancak çözümlerin çoğunun (bunu yayınladığım zamanki gibi) bir hata vereceği bir linux ortamında çalışıyorum.

Sabit kodlama yolu ayırıcıları (ve diğer şeyler) Windows sistemleri dışında herhangi bir şeyde hata verecektir.

Orijinal çözümümde kullandım:

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

Ancak burada bazı cevapları gördükten sonra bunu şöyle ayarladım:

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

2

Bulduğum hiçbir şey bunu gerçekten normalleştirilmiş bir şekilde çözmeye yardımcı olmadığına göre, işte başka bir cevap.

Benzer sorulara verilen bazı yanıtların Uritürü kullanmaya çalıştığını , ancak bunun sondaki eğik çizgilerle ve sondaki eğik çizgilerle mücadele ettiğini unutmayın.

Benim diğer cevabı bu sayfada işe dosya sistemi koymak işlemleri için çalışır, ancak biz dosya sistemi geçmeden, şu anda (örneğin karşılaştırma nedenlerle gibi) çözülmesi yolu olmasını istiyorsanız, eğer C:/Temp/..ve C:/farklı kabul edilir. Dosya sisteminden geçmeden, bu şekilde gezinmek bize normalleştirilmiş, uygun şekilde karşılaştırılabilir bir yol sağlamaz.

Ne yapabiliriz?

Aşağıdaki keşif üzerine inşa edeceğiz:

Path.GetDirectoryName(path + "/") ?? ""olacak güvenilir bize bir dizin yolu vermek bir bölü çizgisi .

  • Eğik çizgi ekleme (aynı string, değil olarak char) bir tedavi edecek nullo davranır olarak yolu aynı "".
  • GetDirectoryName eklenen eğik çizgi sayesinde son yol bileşenini atmaktan kaçınacaktır.
  • GetDirectoryName eğik çizgileri ve gezinme noktalarını normalleştirir.
  • Bu, sondaki eğik çizgilerin kaldırılmasını içerir.
  • Bu, ..yukarı gezinerek daraltmayı içerir .
  • GetDirectoryNamenullbirleştiğimiz boş bir yola döneceğiz "".

Bunu nasıl kullanıyoruz?

İlk olarak, giriş yolunu normalleştirin :

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

Daha sonra, üst dizini alabiliriz ve bu işlemi daha ileri gitmek için istediğiniz kadar tekrar edebiliriz:

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

Dosya sistemine asla dokunmadığımızı unutmayın. Kullanmış olacağımız gibi, yolun hiçbir parçasının var olması gerekmez DirectoryInfo.


1

Bunu yapmaya çalışmamalısın. Environment.CurrentDirectory size çalıştırılabilir dizinin yolunu verir. Bu, .exe dosyasının nerede olduğuna bakılmaksızın tutarlıdır. Geriye doğru göreceli bir konumda olduğu varsayılan bir dosyaya erişmeye çalışmamalısınız

Erişmek istediğiniz kaynağı yerel bir konuma taşımanızı öneririm. Bir sistem dizininin (AppData gibi)


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

bin\Debug\Proje özelliklerinde -> Oluştur -> Çıktı yolundaki " " öğesini temizlerseniz, yalnızcaAppDomain.CurrentDomain.BaseDirectory

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.