ฉันจะค้นหาไดเร็กทอรีหลักใน C # ได้อย่างไร


86

ฉันใช้รหัสนี้เพื่อค้นหาไดเร็กทอรีดีบัก

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

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

ฉันจะค้นหาโฟลเดอร์หลักตามที่แสดงด้านล่างได้อย่างไร

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


16
ทำไมผู้คนถึงใช้ ToString () กับสตริงอยู่เสมอ
Hogan

2
@ โฮแกนในกรณีที่ทรัพย์สินเปลี่ยนแปลง? : D
musefan

คำตอบ:


128

คุณสามารถใช้System.IO.Directory.GetParent()เพื่อดึงข้อมูลไดเร็กทอรีหลักของไดเร็กทอรีที่กำหนด


23
หากไดเรกทอรีมีเครื่องหมายทับคุณต้องโทรหา GetParent สองครั้ง
northben

3
ดูเหมือนว่าจะทำงานบนเส้นทางสัมพัทธ์ (มีความสุขเซอร์ไพรส์) แต่ก็ไม่มีทางที่คุณจะได้ผลลัพธ์กลับมา (เซอร์ไพรส์ที่ไม่มีความสุข)
Adam

16
DirectoryInfo.Parentคุณสามารถหลีกเลี่ยงปัญหาที่ทับลากแทนการใช้ เช่นnew System.IO.DirectoryInfo("c:/path/to/somewhere//").Parent. @northben
mcNux


35

หากคุณต่อท้าย..\..พา ธ ที่มีอยู่ระบบปฏิบัติการจะเรียกดูโฟลเดอร์ grand-parent ได้อย่างถูกต้อง

สิ่งที่ควรทำ:

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

หากคุณเรียกดูเส้นทางนั้นคุณจะเรียกดูไดเร็กทอรี grand-parent


1
มันดูดี แต่น่าเสียดายที่ให้ C: \ Users \ Masoud \ Documents \ Visual Studio 2008 \ Projects \ MyProj \ MyProj \ bin \ Debug \ .. \ ..
StuartQ

ใช่และหากคุณเรียกดูเส้นทางนั้นคุณจะเรียกดูไดเร็กทอรีพาเรนต์
Pierre-Alain Vigeant

ตรงประเด็นฉันจะลบการโหวตลงคะแนนแม้ว่าฉันจะต้องแก้ไขในความคิดเห็นของคุณเพื่อให้ประเด็นกลับมา
StuartQ

3
ผลลัพธ์ของ "Path.Combine" สามารถส่งผ่าน "Path.GetFullPath" เพื่อล้างข้อมูลได้ นั่นคือการไปที่ "C: \ Users \ Masoud \ Documents \ Visual Studio 2008 \ Projects \ MyProj \ MyProj"
Konstantin

1
นี่เป็นวิธีที่ดีที่สุดในการขึ้นหลายระดับใน
Trung Le

19

ฉันพบว่าตัวแปรSystem.IO.Path.Combine(myPath, "..")ที่ง่ายและน่าเชื่อถือที่สุด ยิ่งไปกว่านั้นหากสิ่งที่ northben พูดเป็นความจริง GetParent นั้นต้องการการเรียกพิเศษหากมีเครื่องหมายทับ สำหรับฉันแล้วมันไม่น่าเชื่อถือ

Path.Combine ทำให้แน่ใจว่าคุณจะไม่ผิดพลาดด้วยเครื่องหมายทับ

..ทำงานเหมือนกับที่อื่น ๆ ใน Windows คุณสามารถเพิ่มไฟล์\..ในเส้นทางใน cmd หรือ explorer และมันจะทำงานตามที่ฉันอธิบายไว้ด้านล่าง

..พฤติกรรมพื้นฐานบางประการ:

  1. หากมีชื่อไฟล์..จะตัดออก:

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

  1. หากพา ธ เป็นไดเร็กทอรี..จะเลื่อนระดับขึ้น:

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

  1. ..\.. ปฏิบัติตามกฎเดียวกันสองครั้งติดต่อกัน:

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

  1. และสิ่งนี้มีผลเหมือนกัน:

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


1
ฉันยอมรับว่าวิธีนี้มีข้อดีในการทำงานว่าเส้นทางนั้นมีแบ็กสแลชต่อท้ายหรือไม่ และในสถานการณ์ที่คุณต้องการเส้นทางที่เรียบง่ายโดยไม่มีจุดอยู่คุณสามารถใช้ Path.GetFullPath (() กับผลลัพธ์ได้
RenniePet

1
สองปีต่อมาและฉันพบว่าตัวเองกลับมาที่นี่อีกครั้ง โปรดทราบว่าโดยปกติ Path.GetFullPath (() จะส่งคืนเส้นทางโดยไม่มีแบ็กสแลชต่อท้าย แต่เมื่อคุณเข้าสู่ไดเร็กทอรีรากเช่น "E: \" จะมีแบ็กสแลช
RenniePet

สิ่งนี้ใช้ไม่ได้ทั้งกับ. NET 4.7 หรือ. NET Core 2.1: Path.Combine(@"D:\Grandparent\Parent\Child.txt", @"..")=D:\Grandparent\Parent\Child.txt\..
Métoule

นี่ไม่ได้ตัดชื่อไฟล์สำหรับฉันอย่างน้อยก็ใน MacOS ผ่าน Unity
supergra

@ Métoule @supergra ฉันเห็นความสับสน Path.Combineไม่ตัดทอนสตริงเอง พา ธ ที่เคยใช้เพื่อเข้าถึงระบบไฟล์มีผลตามที่ตั้งใจไว้ อย่างไรก็ตามฉันยอมรับว่านี่เป็นเรื่องที่ไม่เหมาะสม ดูคำตอบล่าสุดของฉันในหน้านี้สำหรับแนวทางที่ปรับเปลี่ยนสตริงแทนที่จะต้องให้ระบบไฟล์แก้ไขเส้นทาง
Timo


8

Directory.GetParentน่าจะเป็นคำตอบที่ดี Path.GetDirectoryNameแต่เพื่อความสมบูรณ์มีวิธีที่แตกต่างกันที่ใช้เวลาและผลตอบแทนสตริงสตริง:

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

1
โปรดทราบว่า Path.GetDirectoryName ไม่สามารถทำงานได้ดีกับพา ธ สัมพัทธ์ .. Directory.GetParent ทำ
nawfal

6

แบบนี้:

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

โชคดี!


1
myDirectory.Parent ToString () ส่งคืนชื่อโฟลเดอร์ย่อยไม่ใช่พา ธ แบบเต็มตรงตามที่ฉันกำลังมองหา นอกจากนี้แทนที่จะทำ Directory.GetParent (Directory.GetParent (str_directory) .ToString ()); ดังที่แสดงไว้ข้างต้นเพียงใช้ myDirectory.parent.parent ToString () รับ 'ปู่ย่าตายาย'
Weihui Guo

1
ฉันพบว่าวิธีนี้ดีที่สุดเพราะจัดการกรณีที่พา ธ ไดเร็กทอรีของคุณมีเครื่องหมายทับ ในขณะที่ถ้าคุณใช้ Directory.GetParent () คุณต้องเรียกมันสองครั้งเพื่อลบเครื่องหมายทับจากนั้นจึงรับพาเรนต์ที่แท้จริง
Magnus


3

เพื่อหลีกเลี่ยงปัญหาเกี่ยวกับการต่อท้าย \ เรียกวิธีนี้ว่า:

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

1
คุณสามารถใช้ได้ในTrimEndกรณีที่คุณต้องการเพียงลบการต่อท้าย`'s . I'm not sure if a leading `ที่สำคัญใน OS อื่น
Walter Stabosz


2

นี่เป็นวิธีที่ใช้บ่อยที่สุด - ขึ้นอยู่กับสิ่งที่คุณกำลังทำจริงๆ: (เพื่ออธิบายตัวอย่างด้านล่างจะลบอักขระ 10 ตัวสุดท้ายซึ่งเป็นสิ่งที่คุณขออย่างไรก็ตามหากมีกฎทางธุรกิจบางอย่างที่ผลักดันความต้องการของคุณ เพื่อค้นหาตำแหน่งเฉพาะคุณควรใช้ตำแหน่งเหล่านั้นเพื่อดึงตำแหน่งไดเร็กทอรีไม่ใช่ค้นหาตำแหน่งของสิ่งอื่นและแก้ไข)

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

สิ่งแรกของคุณจะใช้งานได้ก็ต่อเมื่อคุณรู้ว่าอักขระสุดท้ายนั้นตรงกัน \bin\Debugโดยไม่มี` and no other path, so it's extraordinarily fragile. Your second doesn't work because Environment ต่อท้าย CurrentDirectory` เป็นสตริงและสตริงไม่มีParentคุณสมบัติ
Joe White

@ โจฉันลบตัวที่ 2 ออก แต่ฉันคิดว่านี่เป็นคำตอบที่ถูกต้องหากเส้นทางเป็น \ bin \ debug เสมอมันจะใช้งานได้ และอย่างที่ฉันบอกว่า OP ควรดูจริงๆว่า BR คืออะไรที่ขับเคลื่อนความต้องการไดเร็กทอรีและใช้วิธีการอื่น (ฉันอาจใช้รายการการกำหนดค่า แต่ฉันเดาที่ BR และโครงสร้างโปรแกรม)
Hogan

แม้ว่าจะไม่สมบูรณ์แบบและเปราะบาง แต่ก็เป็นทางออกเดียวที่เหมาะกับฉัน การแก้ไขที่แนะนำ: "str_directory.length" ควรเป็น "str_directory.Length" ไม่ยอมรับ L ตัวพิมพ์เล็ก
OverMars

2

ไม่มีใครให้วิธีแก้ปัญหาที่จะทำงานข้ามรูปแบบ ฉันรู้ว่ามันไม่ได้ถูกถามเป็นพิเศษ แต่ฉันกำลังทำงานในสภาพแวดล้อมลินุกซ์ซึ่งวิธีแก้ปัญหาส่วนใหญ่ (ในขณะที่ฉันโพสต์สิ่งนี้) จะให้ข้อผิดพลาด

ตัวคั่นพา ธ การเข้ารหัส (เช่นเดียวกับสิ่งอื่น ๆ ) จะให้ข้อผิดพลาดในทุกอย่างยกเว้นระบบ Windows

ในโซลูชันดั้งเดิมของฉันฉันใช้:

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

อย่างไรก็ตามหลังจากเห็นคำตอบบางส่วนที่นี่ฉันได้ปรับให้เป็น:

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

2

เนื่องจากไม่มีสิ่งอื่นใดที่ฉันพบว่าช่วยแก้ปัญหานี้ด้วยวิธีที่เป็นมาตรฐานอย่างแท้จริงนี่คือคำตอบอื่น

โปรดทราบว่าบางคำตอบสำหรับคำถามที่คล้ายกันพยายามใช้ไฟล์ Uriประเภทนี้ แต่ก็มีปัญหากับเครื่องหมายทับและไม่มีเครื่องหมายทับ

คำตอบอื่น ๆของฉันในหน้านี้ใช้ได้กับการดำเนินการที่ทำให้ระบบไฟล์ทำงานได้ แต่ถ้าเราต้องการให้เส้นทางที่ได้รับการแก้ไขในขณะนี้ (เช่นเหตุผลในการเปรียบเทียบ) โดยไม่ต้องผ่านระบบไฟล์C:/Temp/..และC:/จะถือว่าแตกต่างกัน โดยไม่ต้องผ่านระบบไฟล์การนำทางในลักษณะนั้นไม่ได้ทำให้เรามีพา ธ ที่เป็นมาตรฐานและเทียบเคียงได้อย่างเหมาะสม

พวกเราทำอะไรได้บ้าง?

เราจะสร้างการค้นพบต่อไปนี้:

Path.GetDirectoryName(path + "/") ?? ""จะน่าเชื่อถือให้เราเส้นทางไดเรกทอรีโดยไม่ต้องเฉือนท้าย

  • เพิ่มทับ (เป็นstring, ไม่เป็นchar) จะรักษาnullเส้นทางเดียวกับที่มันถือว่า""เส้นทางเดียวกับที่มันถือว่า
  • GetDirectoryName จะละเว้นจากการทิ้งส่วนประกอบเส้นทางสุดท้ายเนื่องจากเครื่องหมายทับที่เพิ่มเข้ามา
  • GetDirectoryName จะทำให้เครื่องหมายทับและจุดนำทางเป็นปกติ
  • ซึ่งรวมถึงการลบเครื่องหมายทับ
  • ซึ่งรวมถึงการยุบ..โดยการนำทางขึ้น
  • GetDirectoryNameจะกลับมาสำหรับเส้นทางที่ว่างเปล่าที่เราจะเชื่อมต่อกันnull""

เราจะใช้สิ่งนี้อย่างไร?

ขั้นแรกปรับเส้นทางอินพุตให้เป็นปกติ :

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

จากนั้นเราจะได้รับไดเรกทอรีหลักและเราสามารถทำซ้ำการดำเนินการนี้กี่ครั้งก็ได้เพื่อนำทางต่อไป:

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

โปรดทราบว่าเราไม่เคยสัมผัสระบบไฟล์ DirectoryInfoส่วนใดส่วนหนึ่งของเส้นทางความต้องการที่จะมีชีวิตอยู่ในขณะที่มันจะถ้าเราได้ใช้


1

คุณไม่ควรพยายามทำเช่นนั้น Environment.CurrentDirectory ให้เส้นทางของไดเร็กทอรีปฏิบัติการ สิ่งนี้สอดคล้องกันไม่ว่าไฟล์. exe จะอยู่ที่ใด คุณไม่ควรพยายามเข้าถึงไฟล์ที่สันนิษฐานว่าอยู่ในตำแหน่งสัมพัทธ์ย้อนหลัง

ฉันขอแนะนำให้คุณย้ายทรัพยากรใด ๆ ที่คุณต้องการเข้าถึงไปยังสถานที่ในท้องถิ่น ของไดเร็กทอรีระบบ (เช่น AppData)


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

หากคุณล้าง " bin\Debug\" ในคุณสมบัติโครงการ -> สร้าง -> เส้นทางเอาต์พุตคุณก็สามารถใช้ได้AppDomain.CurrentDomain.BaseDirectory

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.