जावा में पुनरावर्ती निर्देशिका हटाएं


382

क्या जावा में पुनरावर्ती संपूर्ण निर्देशिकाओं को हटाने का कोई तरीका है?

सामान्य स्थिति में खाली निर्देशिका को हटाना संभव है। हालाँकि जब संपूर्ण निर्देशिकाओं को सामग्री के साथ हटाने की बात आती है, तो यह उतना सरल नहीं है।

जावा में सामग्री के साथ पूरी निर्देशिका कैसे हटाएं?


4
File.delete () को केवल गैर-रिक्त निर्देशिका के साथ कॉल करने पर गलत वापस करना चाहिए।
बेन एस

यदि आप Java 8 का उपयोग कर रहे हैं, तो @ RoK का उत्तर देखें।
रॉबिन

जवाबों:


462

आपको अपाचे के कॉमन्स-आईओ की जांच करनी चाहिए । इसमें एक FileUtils वर्ग है जो वह करेगा जो आप चाहते हैं।

FileUtils.deleteDirectory(new File("directory"));

3
यह फ़ंक्शन संभवतः उस कोड को लपेटता है जो उसके उत्तर में दिए गए एरिकसन को प्रदान करता है।
पावेलोकेक

14
यह थोड़ा और पूरी तरह से है। यह लिनक्स / यूनिक्स पर सही ढंग से प्रतीकात्मक लिंक जैसी चीजों को संभालता है। svn.apache.org/viewvc/commons/proper/io/trunk/src/java/org/…
स्टीव के



जावा से बॉक्स में सुविधा होने पर एक और निर्भरता क्यों जोड़ें? इस पृष्ठ पर RoK द्वारा उत्तर देखें, या stackoverflow.com/questions/35988192/…
foo

190

जावा 7 के साथ, हम अंत में विश्वसनीय सिम्लिंक का पता लगाने के साथ कर सकते हैं (मैं अपाचे के कॉमन्स-आईओओ को इस समय विश्वसनीय सिम्क्लिन का पता लगाने के लिए नहीं मानता , क्योंकि यह विंडोज के साथ लिंक को संभाल नहीं पाता है mklink)।

इतिहास के लिए, यहां एक पूर्व-जावा 7 उत्तर दिया गया है, जो सहानुभूति का अनुसरण करता है।

void delete(File f) throws IOException {
  if (f.isDirectory()) {
    for (File c : f.listFiles())
      delete(c);
  }
  if (!f.delete())
    throw new FileNotFoundException("Failed to delete file: " + f);
}

11
File.delete () में वह कार्यक्षमता नहीं है।
बेन एस

14
@ एरिकसन: डिलीट असफलता के लिए FileNotFoundException खराब अपवाद नहीं है? यदि फ़ाइल वास्तव में अब नहीं है, तो यह पहले ही हटा दिया गया होगा, जिसका अर्थ है कि, शब्दार्थ, डिलीट विफल नहीं हुआ - इसका कोई लेना-देना नहीं था। और अगर यह किसी अन्य कारण से विफल हो गया, तो ऐसा नहीं था क्योंकि फ़ाइल नहीं मिली थी।
लॉरेंस डोल

46
बहुत सावधान रहें । यह सहानुभूति को कम करेगा। यदि आप उदा लिनक्स पर हैं, और fooएक लिंक के साथ एक फ़ोल्डर foo/linkहै link->/, जैसे कि कॉलिंग delete(new File(foo)) आपके फाइल सिस्टम को उतना ही हटा देगा जितना कि आपके उपयोगकर्ता को अनुमति है !!
मिकेल

4
@ मायिक का कोई मतलब नहीं है - हम क्यों सावधान रहना चाहेंगे? निश्चित रूप से प्रदान किए गए कोड का बिंदु एक संपूर्ण निर्देशिका को निकालना है, जो कि ऐसा करना प्रतीत होता है। मुझे समझ नहीं आ रहा है कि यहां क्या खतरा है।
जोहोते २००

12
@ जोहोते 200 आप सही कह रहे हैं, डाइरेक्टरी सिमिलिंक पर डिलीट कॉलिंग डायरेक्टरी को डिलीट नहीं करेगा, सिर्फ़ सिम्लिंक ही। निर्देशिका को हटाना वास्तव में ReadSymbolicLink का उपयोग करते हुए सिम्लिंक का स्पष्ट रूप से पालन करने की आवश्यकता होगी । मेरी गलती! अच्छी तरह से देखा
मिकेल

148

Java 7+ में आप Filesक्लास का उपयोग कर सकते हैं । कोड बहुत सरल है:

Path directory = Paths.get("/tmp");
Files.walkFileTree(directory, new SimpleFileVisitor<Path>() {
   @Override
   public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
       Files.delete(file);
       return FileVisitResult.CONTINUE;
   }

   @Override
   public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
       Files.delete(dir);
       return FileVisitResult.CONTINUE;
   }
});

2
यह समाधान बहुत ही सुरुचिपूर्ण लगता है और इसमें कोई निर्देशिका ट्रैवर्सल तर्क नहीं होता है!
जीरो 3

1
"मोती को समुद्र में गहरा गोता लगाने के लिए।" यह अब तक का सबसे साफ समाधान है। इसे खोजने के लिए गहरा गोता लगाना पड़ा। प्रतिभाशाली!
तुलसी मूसा

20
"कोड" बहुत आसान नहीं है "बस एक dir को मिटाने के लिए :-) लेकिन अरे, यह शुद्ध जावा मैं सबसे अच्छा समाधान है।
Mat

1
कृपया ध्यान दें कि यहां इस्तेमाल किया जाने वाला वॉकफाइलट्री ओवरलोड " प्रतीकात्मक लिंक का पालन नहीं करता है "। ( जावदोक : docs.oracle.com/javase/7/docs/api/java/nio/file/… )
स्टीफन

1
अगर चलना एक निर्देशिका को सूचीबद्ध नहीं कर सका, तो आपको संभवतः super.postVisitDirectory(dir, exc);अपने postVisitDirectoryतरीके से कॉल करना चाहिए ।
टॉम एंडरसन

68

एक-लाइनर समाधान (Java8) सभी फाइलों और निर्देशिकाओं को हटाने के लिए, जिसमें शुरुआती निर्देशिका शामिल है:

Files.walk(Paths.get("c:/dir_to_delete/"))
                .map(Path::toFile)
                .sorted((o1, o2) -> -o1.compareTo(o2))
                .forEach(File::delete);

हम उल्टे क्रम के लिए एक तुलनित्र का उपयोग करते हैं, अन्यथा फ़ाइल :: हटाएं संभवतः गैर-रिक्त निर्देशिका को हटाने में सक्षम नहीं होंगी। इसलिए, यदि आप निर्देशिकाओं को रखना चाहते हैं और केवल फाइलों को हटाना चाहते हैं तो सॉर्ट करने वाले को हटा दें () या पूरी तरह से छंटनी को हटा दें और फाइलों को फ़िल्टर करें:

Files.walk(Paths.get("c:/dir_to_delete/"))
                .filter(Files::isRegularFile)
                .map(Path::toFile)
                .forEach(File::delete);

1
सभी निर्देशिकाओं को हटाने के लिए आपको पहले एक .sorted (तुलनित्र :: रिवर्सऑडर) में सॉर्ट को बदलने की आवश्यकता है । अन्यथा बच्चे से पहले माता-पिता की निर्देशिका का आदेश दिया जाता है, और इस तरह से खाली नहीं होने के बाद इसे हटा नहीं दिया जाएगा। जावा 8 का उपयोग करने वालों के लिए शानदार उत्तर!
रॉबिन

1
सही तरीका यह है .sorted(Comparator.reverseOrder())कि सुझाव Comparator::reverseOrderकाम नहीं करता है। देखें: stackoverflow.com/questions/43036611/…
user1156544

4
रॉबिन, "-o1.compareTo (o2)" में माइनस साइन पर ध्यान दें। यह वही .sorted के रूप में (Comparator.reverseOrder) है
कोरिया गणराज्य

Files.walk अनुक्रमिक है? या गैर-खाली निर्देशिकाओं को हटाने की कोशिश से बचने के लिए क्या इस जवाब के लिए forEach की बजाय forEachOrdered की आवश्यकता है?
सिल्विंग

बस का उपयोग करें: .sorted((f1, f2) -> f2.compareTo(f1)), की तुलना f2के साथ f1के बजाय f1साथ f2
बेटो नेटो

67

जावा 7 ने सिमिलिंक हैंडलिंग के साथ चलने वाली निर्देशिकाओं के लिए समर्थन जोड़ा:

import java.nio.file.*;

public static void removeRecursive(Path path) throws IOException
{
    Files.walkFileTree(path, new SimpleFileVisitor<Path>()
    {
        @Override
        public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
                throws IOException
        {
            Files.delete(file);
            return FileVisitResult.CONTINUE;
        }

        @Override
        public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException
        {
            // try to delete the file anyway, even if its attributes
            // could not be read, since delete-only access is
            // theoretically possible
            Files.delete(file);
            return FileVisitResult.CONTINUE;
        }

        @Override
        public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException
        {
            if (exc == null)
            {
                Files.delete(dir);
                return FileVisitResult.CONTINUE;
            }
            else
            {
                // directory iteration failed; propagate exception
                throw exc;
            }
        }
    });
}

मैं इसे प्लेटफ़ॉर्म-विशिष्ट विधियों (इस अप्राप्त कोड में) से एक कमबैक के रूप में उपयोग करता हूं :

public static void removeDirectory(Path directory) throws IOException
{
    // does nothing if non-existent
    if (Files.exists(directory))
    {
        try
        {
            // prefer OS-dependent directory removal tool
            if (SystemUtils.IS_OS_WINDOWS)
                Processes.execute("%ComSpec%", "/C", "RD /S /Q \"" + directory + '"');
            else if (SystemUtils.IS_OS_UNIX)
                Processes.execute("/bin/rm", "-rf", directory.toString());
        }
        catch (ProcessExecutionException | InterruptedException e)
        {
            // fallback to internal implementation on error
        }

        if (Files.exists(directory))
            removeRecursive(directory);
    }
}

(SystemUtils Apache Commons Lang से है । प्रक्रियाएं निजी हैं लेकिन इसका व्यवहार स्पष्ट होना चाहिए।)


मुझे Files.walkFileTree के साथ एक समस्या मिलती है - यह रिकर्सिव डिलीट के एक संस्करण को लागू करने के लिए अपर्याप्त है जहां आप विकल्पों से बाहर निकलने तक फ़ाइलों को हटाते रहते हैं। यह एक असफल-फास्ट संस्करण के लिए पर्याप्त है, लेकिन असफल-तेज़ हमेशा वह नहीं होता है जो आप चाहते हैं (जैसे कि यदि आप अस्थायी फ़ाइलों को साफ कर रहे हैं, तो आप अभी हटाना चाहते हैं, असफल-तेज़ नहीं।)
ट्रेकज़ाज़

मैं नहीं देखता कि यह सच क्यों है। आप चाहते हैं कि त्रुटियों को संभाल सकते हैं - आप तेजी से विफल करने के लिए आवश्यक नहीं हैं। एकमात्र मुद्दा जो मैं समझ सकता था कि यह वर्तमान निर्देशिका के चलने के दौरान बनाई जा रही नई फ़ाइलों को संभाल नहीं सकता है, लेकिन यह एक अनोखी स्थिति है जो कस्टम समाधान के लिए बेहतर है।
ट्रेवर रॉबिन्सन

1
यदि आप visitFile से त्रुटि को दबाते हैं और एक भी फ़ाइल पर walkFileTree को कॉल करते हैं, जो विफल हो जाती है, तो आपको कोई त्रुटि नहीं मिलती है (इसलिए विज़िटफ़ाइल को किसी भी त्रुटि का प्रचार करना चाहिए ।) यदि आप एक निर्देशिका को हटा रहे हैं और एक फ़ाइल को हटाने में विफल हैं, तो एकमात्र कॉलबैक कहा जाता है। PostVisitDirectory है। यदि आप एक फ़ाइल पर जाकर कोई त्रुटि प्राप्त करते हैं, तो यह निर्देशिका में अन्य फ़ाइलों का दौरा नहीं करता है। मेरा मतलब यह है। मुझे यकीन है कि इसके आस-पास काम करने का कोई तरीका है, लेकिन जब तक हम इस बिंदु पर पहुंचते हैं तब तक हम पहले से ही एक पारंपरिक पुनरावर्ती डिलीट रूटीन की तुलना में अधिक कोड लिख चुके थे, इसलिए हमने इसका उपयोग करने के खिलाफ फैसला किया।
तर्जक

आपके पहले कोड के लिए धन्यवाद, यह मेरे लिए उपयोगी था, लेकिन मुझे इसे बदलना पड़ा, क्योंकि यह एक सरल डीलट्री को पूरा नहीं करता था: मुझे "पोस्टविसडायरेक्टरी" में अपवाद को नजरअंदाज करना पड़ा और इसकी परवाह किए बिना वापस लौटना पड़ा, क्योंकि निम्नलिखित सरल पेड़ पूरी तरह से नहीं हो सकते हैं हटाए जाएं: एक निर्देशिका जिसके अंदर एक और निर्देशिका थी जिसमें एक फ़ाइल थी। जो सभी विंडोज पर सरल / सामान्य के रूप में मिलता है।
ड्रीमस्पेस अध्यक्ष

यह सब एक java.nio.file से शुरू हुआ। IndirectNotEmptyException मुझे मिला। मुझे उस मामले का पता चला जहां visitFileFailed का उपयोग किया जाता है। यदि आपकी निर्देशिका संरचना में विंडोज़ में एक जंक्शन प्रकार लिंक है। इससे आपको 2 समस्याएँ हो सकती हैं: *) Files.walkFileTree जंक्शन में लिंक का अनुसरण करता है और वहां सब कुछ हटा देता है। *) अगर जंक्शन टारगेट डायरेक्टरी पहले ही डिलीट हो गई है तो Files.walkFileTree के लिंक को पार्स करना NoSuchFileException के साथ फेल हो जाता है, जो visitFileFailed में कैच होता है।
एंड्रेस ल्यूक

34

बस देखा कि मेरा समाधान कमोबेश उसी तरह से है जैसे कि इरिकसन, सिर्फ एक स्टैटिक विधि के रूप में पैक किया गया है। इसे कहीं छोड़ दें, यह कुछ के लिए अपाचे कॉमन्स को स्थापित करने की तुलना में बहुत हल्का वजन है (जैसा कि आप देख सकते हैं) काफी सरल है।

public class FileUtils {
    /**
     * By default File#delete fails for non-empty directories, it works like "rm". 
     * We need something a little more brutual - this does the equivalent of "rm -r"
     * @param path Root File Path
     * @return true iff the file and all sub files/directories have been removed
     * @throws FileNotFoundException
     */
    public static boolean deleteRecursive(File path) throws FileNotFoundException{
        if (!path.exists()) throw new FileNotFoundException(path.getAbsolutePath());
        boolean ret = true;
        if (path.isDirectory()){
            for (File f : path.listFiles()){
                ret = ret && deleteRecursive(f);
            }
        }
        return ret && path.delete();
    }
}

20

स्टैक के साथ और पुनरावर्ती तरीकों के बिना एक समाधान:

File dir = new File("/path/to/dir");
File[] currList;
Stack<File> stack = new Stack<File>();
stack.push(dir);
while (! stack.isEmpty()) {
    if (stack.lastElement().isDirectory()) {
        currList = stack.lastElement().listFiles();
        if (currList.length > 0) {
            for (File curr: currList) {
                stack.push(curr);
            }
        } else {
            stack.pop().delete();
        }
    } else {
        stack.pop().delete();
    }
}

2
स्टैक का उपयोग करने के लिए +1। यह उन निर्देशिकाओं के साथ काम करेगा जिनमें नेस्टेड उपनिर्देशिकाओं के गहरे स्तर होते हैं जबकि अन्य स्टैक-आधारित दृष्टिकोण विफल हो जाएंगे।
नाथन उस्मान

4
यह देखते हुए कि आमतौर पर आपको सौ तरीकों की एक-दो कॉल करने में समस्या नहीं होती है, मुझे लगता है कि आप बहुत पहले फाइल सिस्टम प्रतिबंधों में चलने की संभावना रखते हैं।
बोम्बे

2
list*कक्षा के लिए तरीकों से सावधान रहें java.io.File। Javadocs से: "यदि यह सार पथनाम एक निर्देशिका को निरूपित नहीं करता है, या यदि I / O त्रुटि उत्पन्न होती है, तो वापस आता है।" तो: if (currList.length > 0) {बन जाता हैif (null != currList && currList.length > 0) {
kevinarpe

1
मैं एक स्टैक के बजाय एक ArrayDeque का उपयोग करता हूं जो थोड़ा तेज है। (unsynchronized)
Wytze


15

अमरूद को 9Files.deleteRecursively(File) तक समर्थन दिया था ।

से अमरूद 10 :

पदावनत। यह पद्धति खराब सीलिंक का पता लगाने और दौड़ की स्थिति से ग्रस्त है। इस कार्यक्षमता को केवल एक ऑपरेटिंग सिस्टम कमांड जैसे कि rm -rfया बाहर गोलाबारी द्वारा उपयुक्त रूप से समर्थित किया जा सकता है del /sइस विधि को अमरूद से गुवा में 11.0 रिलीज किया जाना है।

इसलिए, अमरूद 11 में ऐसी कोई विधि नहीं है ।


6
बहुत बुरा। शेलिंग थोड़ा क्रूड और पोर्टेबल नहीं लगता है। यदि अपाचे कॉमन्स संस्करण ठीक से काम करता है, तो संभवतः इसे लागू करना असंभव नहीं है।
एंड्रयू मैककिनले

6
@andrew अपाचे कॉमन्स कार्यान्वयन के समान ही समस्या नहीं होनी चाहिए अमरूद उनके कार्यान्वयन को दूर करने के कारण यह है कि, देख code.google.com/p/guava-libraries/issues/detail?id=365
orip

अपाचे कॉमन्स संस्करण सीमलिंक का पता लगाता है, और बस फ़ाइल के बच्चों को पार नहीं करता है।
अजाक्स

5
अमरूद 21.0 ने इसे MoreFiles.deleteRecursively () के रूप में जोड़ा ।
रॉबर्ट फ्लेमिंग

12
for(Path p : Files.walk(directoryToDelete).
        sorted((a, b) -> b.compareTo(a)). // reverse; files before dirs
        toArray(Path[]::new))
{
    Files.delete(p);
}

या यदि आप संभालना चाहते हैं IOException:

Files.walk(directoryToDelete).
    sorted((a, b) -> b.compareTo(a)). // reverse; files before dirs
    forEach(p -> {
        try { Files.delete(p); }
        catch(IOException e) { /* ... */ }
      });

2
इससे मुझे स्कैला संस्करण के साथ आने में मदद मिली:Files.walk(path).iterator().toSeq.reverse.foreach(Files.delete)
जेम्स वार्ड

क्या वास्तव में छंटनी आवश्यक है? walkविधि पहले से ही एक गहराई-प्रथम ट्रेवर्सल गारंटी देता है।
वीजीआर

तुलनित्र को पुनर्नवीनीकरण किया जा सकता है Collections.reverseOrder()ताकि आपका कोड for (Path p : Files.walk(directoryToDelete).sorted(reverseOrder()).toArray(Path[]::new))यह मान ले कि यह सांख्यिकीय रूप से आयात किया गया है।
namero999

@ namero999 क्या आपका मतलब है Comparator.reverseOrder? Files.walk(dir) .sorted(Comparator.reverseOrder()) .toArray(Path[]::new))
जेफ

@ आप निश्चित रूप से सही हैं, ज्यादातर वहां मेमोरी से चले गए :)
namero999

11
public void deleteRecursive(File path){
    File[] c = path.listFiles();
    System.out.println("Cleaning out folder:" + path.toString());
    for (File file : c){
        if (file.isDirectory()){
            System.out.println("Deleting file:" + file.toString());
            deleteRecursive(file);
            file.delete();
        } else {
            file.delete();
        }
    }
    path.delete();
}

5
बूलियन वापसी मूल्य और कोई दोहराव के साथ उन्नत संस्करण: pastebin.com/PqJyzQUx
एरिक कप्लून

9
static public void deleteDirectory(File path) 
{
    if (path == null)
        return;
    if (path.exists())
    {
        for(File f : path.listFiles())
        {
            if(f.isDirectory()) 
            {
                deleteDirectory(f);
                f.delete();
            }
            else
            {
                f.delete();
            }
        }
        path.delete();
    }
}

अच्छा कोड है, लेकिन तय होने पर एक बग है, यह काम करता है। के f.delete()तहत लाइन deleteDirectory(f)NoSuchFileException फेंकता है क्योंकि deleteDirectory(f)पहले से ही उस फ़ाइल को हटा देगा। हर निर्देशिका एक मार्ग बन जाएगी जब उसमें से पारित किया जाएगा deleteDirectory(f)और हटा दिया जाएगा path.delete()। इसलिए, हम की जरूरत नहीं है f.delete()में if f.isDerectoryखंड। इसलिए, बस f.delete();डिलीटडायरेक्टरी (एफ) के तहत डिलीट करें और यह काम करेगा।
ट्राइएग गुयेन

5

सिमिलिंक और उपरोक्त कोड के साथ विफल होने के दो तरीके ... और समाधान नहीं जानते हैं।

रास्ता # 1

परीक्षण बनाने के लिए इसे चलाएं:

echo test > testfile
mkdir dirtodelete
ln -s badlink dirtodelete/badlinktodelete

यहां आप अपनी परीक्षण फ़ाइल और परीक्षण निर्देशिका देखें:

$ ls testfile dirtodelete
testfile

dirtodelete:
linktodelete

फिर अपने कॉमन्स-आईओ डिलीटडायरेरी () चलाएं। यह कहते हुए क्रैश हो जाता है कि फ़ाइल नहीं मिली है। निश्चित नहीं कि अन्य उदाहरण यहाँ क्या करते हैं। लिनक्स आरएम कमांड केवल लिंक को हटा देगा, और आरएम-आर निर्देशिका पर भी होगा।

Exception in thread "main" java.io.FileNotFoundException: File does not exist: /tmp/dirtodelete/linktodelete

रास्ता # 2

परीक्षण बनाने के लिए इसे चलाएं:

mkdir testdir
echo test > testdir/testfile
mkdir dirtodelete
ln -s ../testdir dirtodelete/dirlinktodelete

यहां आप अपनी परीक्षण फ़ाइल और परीक्षण निर्देशिका देखें:

$ ls dirtodelete testdir
dirtodelete:
dirlinktodelete

testdir:
testfile

फिर अपने कॉमन-आईओ डिलीटडायरेरी () या पोस्ट किए गए उदाहरण कोड लोगों को चलाएं। यह न केवल डायरेक्टरी को डिलीट करता है, बल्कि आपका टेस्टफाइल जो डायरेक्ट्री डिलीट होने के बाहर है। (यह निर्देशिका को संक्षेप में प्रस्तुत करता है, और सामग्री को हटाता है)। rm -r केवल लिंक को हटा देगा। आपको इस तरह की कुछ चीज़ों का उपयोग करने की आवश्यकता है जो कि डिरेल्ड फाइल्स को डिलीट करें: "-L dirtodelete -type f -exec rm {} \";

$ ls dirtodelete testdir
ls: cannot access dirtodelete: No such file or directory
testdir:

4

आप उपयोग कर सकते हैं:

org.apache.commons.io.FileUtils.deleteQuietly(destFile);

एक फ़ाइल को हटाता है, कभी अपवाद नहीं फेंकता। यदि फ़ाइल एक निर्देशिका है, तो उसे और सभी उप-निर्देशिकाओं को हटा दें। File.delete () और इस पद्धति के बीच का अंतर हैं: हटाई जाने वाली निर्देशिका को खाली नहीं होना चाहिए। कोई अपवाद नहीं फेंका जाता है जब एक फ़ाइल या निर्देशिका को हटाया नहीं जा सकता।


4

एक इष्टतम समाधान जो अपवाद को लगातार दृष्टिकोण के साथ संभालता है कि एक विधि से फेंका गया अपवाद हमेशा यह वर्णन करना चाहिए कि वह विधि क्या करने की कोशिश कर रही थी (और विफल रही):

private void deleteRecursive(File f) throws Exception {
    try {
        if (f.isDirectory()) {
            for (File c : f.listFiles()) {
                deleteRecursive(c);
            }
        }
        if (!f.delete()) {
            throw new Exception("Delete command returned false for file: " + f);
        }
    } 
    catch (Exception e) {
        throw new Exception("Failed to delete the folder: " + f, e);
    }
}

3

विरासत परियोजनाओं में, मुझे मूल जावा कोड बनाने की आवश्यकता है। मैं इस कोड को पॉलिटेक्स कोड के समान बनाता हूं। देखना है कि:

public class FileHelper {

   public static boolean delete(File fileOrFolder) {
      boolean result = true;
      if(fileOrFolder.isDirectory()) {
         for (File file : fileOrFolder.listFiles()) {
            result = result && delete(file);
         }
      }
      result = result && fileOrFolder.delete();
      return result;
   } 
}

और इकाई परीक्षण:

public class FileHelperTest {

    @Before
    public void setup() throws IOException {
       new File("FOLDER_TO_DELETE/SUBFOLDER").mkdirs();
       new File("FOLDER_TO_DELETE/SUBFOLDER_TWO").mkdirs();
       new File("FOLDER_TO_DELETE/SUBFOLDER_TWO/TEST_FILE.txt").createNewFile();
    }

    @Test
    public void deleteFolderWithFiles() {
       File folderToDelete = new File("FOLDER_TO_DELETE");
       Assert.assertTrue(FileHelper.delete(folderToDelete));
       Assert.assertFalse(new File("FOLDER_TO_DELETE").exists());
    }

}

3

नीचे दिए गए कोड पुन: किसी दिए गए फ़ोल्डर में सभी सामग्रियों को हटा दें।

boolean deleteDirectory(File directoryToBeDeleted) {
    File[] allContents = directoryToBeDeleted.listFiles();
    if (allContents != null) {
        for (File file : allContents) {
            deleteDirectory(file);
        }
    }
    return directoryToBeDeleted.delete();
}

2

यहां एक नंगे हड्डियों का मुख्य तरीका है जो एक कमांड लाइन तर्क को स्वीकार करता है, आपको अपनी स्वयं की त्रुटि की जांच करने या इसे कैसे आप फिट करने के लिए ढालना है, इसकी आवश्यकता हो सकती है।

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;

public class DeleteFiles {

/**
 * @param intitial arguments take in a source to read from and a 
 * destination to read to
 */
    public static void main(String[] args)
                     throws FileNotFoundException,IOException {
        File src = new File(args[0]);
        if (!src.exists() ) {
            System.out.println("FAILURE!");
        }else{
            // Gathers files in directory
            File[] a = src.listFiles();
            for (int i = 0; i < a.length; i++) {
                //Sends files to recursive deletion method
                fileDelete(a[i]);
            }
            // Deletes original source folder
            src.delete();
            System.out.println("Success!");
        }
    }

    /**
     * @param srcFile Source file to examine
     * @throws FileNotFoundException if File not found
     * @throws IOException if File not found
     */
    private static void fileDelete(File srcFile)
                     throws FileNotFoundException, IOException {
        // Checks if file is a directory
        if (srcFile.isDirectory()) {
            //Gathers files in directory
            File[] b = srcFile.listFiles();
            for (int i = 0; i < b.length; i++) {
                //Recursively deletes all files and sub-directories
                fileDelete(b[i]);
            }
            // Deletes original sub-directory file
            srcFile.delete();
        } else {
            srcFile.delete();
        }
    }
}

मुझे आशा है कि वह मदद करेंगे!


1

हो सकता है कि इस समस्या का एक समाधान इरिकसन के उत्तर से कोड का उपयोग करके फ़ाइल वर्ग की डिलीट विधि को फिर से लागू करना हो:

public class MyFile extends File {

  ... <- copy constructor

  public boolean delete() {
    if (f.isDirectory()) {
      for (File c : f.listFiles()) {
        return new MyFile(c).delete();
      }
    } else {
        return f.delete();
    }
  }
}

1
मुझे लगता है कि इसे लागू किया गया है क्योंकि यह "rm", "rmdir" और "del" जैसी अधिकांश कमांड शेल उपयोगिताओं के व्यवहार की नकल करने के लिए है। दो विकल्पों में से, वर्तमान कार्यान्वयन निश्चित रूप से समग्र आश्चर्य (और क्रोध) क्षमता को कम करता है। यह बदलने वाला नहीं है।
इरिकसन

4
आमतौर पर, केवल जावा JRE पैकेज जो मैं देख रहा हूं, वे स्विंग से हैं। आमतौर पर, अन्य वर्गों जैसे कि java.io.File का विस्तार करना एक बुरा विचार है, क्योंकि इसमें चीजों को अप्रत्याशित तरीके से काम करने की संभावना है।
एडी

1

कॉमन्स आईओ और <जावा एसई 7 के बिना

public static void deleteRecursive(File path){
            path.listFiles(new FileFilter() {
                @Override
                public boolean accept(File pathname) {
                    if (pathname.isDirectory()) {
                        pathname.listFiles(this);
                        pathname.delete();
                    } else {
                        pathname.delete();
                    }
                    return false;
                }
            });
            path.delete();
        }

0

जबकि file.delete () का उपयोग करके फ़ाइलों को आसानी से हटाया जा सकता है, निर्देशिकाओं को हटाने के लिए खाली होना आवश्यक है। इसे आसानी से करने के लिए पुनरावृत्ति का उपयोग करें। उदाहरण के लिए:

public static void clearFolders(String[] args) {
        for(String st : args){
            File folder = new File(st);
            if (folder.isDirectory()) {
                File[] files = folder.listFiles();
                if(files!=null) { 
                    for(File f: files) {
                        if (f.isDirectory()){
                            clearFolders(new String[]{f.getAbsolutePath()});
                            f.delete();
                        } else {
                            f.delete();
                        }
                    }
                }
            }
        }
    }

0

मैंने इस दिनचर्या को कोडित किया है जिसमें सुरक्षित उपयोग के लिए 3 सुरक्षा मानदंड हैं।

package ch.ethz.idsc.queuey.util;

import java.io.File;
import java.io.IOException;

/** recursive file/directory deletion
 * 
 * safety from erroneous use is enhanced by three criteria
 * 1) checking the depth of the directory tree T to be deleted
 * against a permitted upper bound "max_depth"
 * 2) checking the number of files to be deleted #F
 * against a permitted upper bound "max_count"
 * 3) if deletion of a file or directory fails, the process aborts */
public final class FileDelete {
    /** Example: The command
     * FileDelete.of(new File("/user/name/myapp/recordings/log20171024"), 2, 1000);
     * deletes given directory with sub directories of depth of at most 2,
     * and max number of total files less than 1000. No files are deleted
     * if directory tree exceeds 2, or total of files exceed 1000.
     * 
     * abort criteria are described at top of class
     * 
     * @param file
     * @param max_depth
     * @param max_count
     * @return
     * @throws Exception if criteria are not met */
    public static FileDelete of(File file, int max_depth, int max_count) throws IOException {
        return new FileDelete(file, max_depth, max_count);
    }

    // ---
    private final File root;
    private final int max_depth;
    private int removed = 0;

    /** @param root file or a directory. If root is a file, the file will be deleted.
     *            If root is a directory, the directory tree will be deleted.
     * @param max_depth of directory visitor
     * @param max_count of files to delete
     * @throws IOException */
    private FileDelete(final File root, final int max_depth, final int max_count) throws IOException {
        this.root = root;
        this.max_depth = max_depth;
        // ---
        final int count = visitRecursively(root, 0, false);
        if (count <= max_count) // abort criteria 2)
            visitRecursively(root, 0, true);
        else
            throw new IOException("more files to be deleted than allowed (" + max_count + "<=" + count + ") in " + root);
    }

    private int visitRecursively(final File file, final int depth, final boolean delete) throws IOException {
        if (max_depth < depth) // enforce depth limit, abort criteria 1)
            throw new IOException("directory tree exceeds permitted depth");
        // ---
        int count = 0;
        if (file.isDirectory()) // if file is a directory, recur
            for (File entry : file.listFiles())
                count += visitRecursively(entry, depth + 1, delete);
        ++count; // count file as visited
        if (delete) {
            final boolean deleted = file.delete();
            if (!deleted) // abort criteria 3)
                throw new IOException("cannot delete " + file.getAbsolutePath());
            ++removed;
        }
        return count;
    }

    public int deletedCount() {
        return removed;
    }

    public void printNotification() {
        int count = deletedCount();
        if (0 < count)
            System.out.println("deleted " + count + " file(s) in " + root);
    }
}

0

खैर, चलिए एक उदाहरण देते हैं,

import java.io.File;
import java.io.IOException;

public class DeleteDirectory
{
   private static final String folder = "D:/project/java";

   public static void main(String[] args) throws IOException
   {
      File fl = new File(folder);
      if(!fl.exists()) // checking if directory exists
      {
         System.out.println("Sorry!! directory doesn't exist.");
      }
      else
      {
         DeleteDirectory dd = new DeleteDirectory();
         dd.deleteDirectory(fl);
      }
   }

   public void deleteDirectory(File file) throws IOException
   {
      if(file.isDirectory())
      {
         if(file.list().length == 0)
         { 
            deleteEmptyDirectory(file); // here if directory is empty delete we are deleting
         }
         else
         {
            File fe[] = file.listFiles();
            for(File deleteFile : fe)
            {
               deleteDirectory(deleteFile); // recursive call
            }
            if(file.list().length == 0)
            {
               deleteEmptyDirectory(file);
            }
         }
      }
      else
      {
         file.delete();
         System.out.println("File deleted : " + file.getAbsolutePath());
      }
   }

   private void deleteEmptyDirectory(File fi)
   {
      fi.delete();
      System.out.println("Directory deleted : " + fi.getAbsolutePath());
   }
}

अधिक जानकारी के लिए नीचे संसाधन देखें

निर्देशिका हटाएं


0

rm -rfकी तुलना में बहुत अधिक प्रदर्शन था FileUtils.deleteDirectory

व्यापक बेंचमार्किंग के बाद, हमने पाया कि उपयोग करने rm -rfकी तुलना में उपयोग कई गुना अधिक तेज थाFileUtils.deleteDirectory

बेशक, यदि आपके पास एक छोटी या सरल निर्देशिका है, तो इससे कोई फर्क नहीं पड़ेगा, लेकिन हमारे मामले में हमारे पास कई गीगाबाइट्स और गहरी नेस्टेड उप निर्देशिकाएं थीं, जहां 10 मिनट से अधिक FileUtils.deleteDirectoryऔर केवल 1 मिनट का समय लगेगा rm -rf

यहाँ ऐसा करने के लिए हमारे मोटे तौर पर जावा कार्यान्वयन है:

// Delete directory given and all subdirectories and files (i.e. recursively).
//
static public boolean deleteDirectory( File file ) throws IOException, InterruptedException {

    if ( file.exists() ) {

        String deleteCommand = "rm -rf " + file.getAbsolutePath();
        Runtime runtime = Runtime.getRuntime();

        Process process = runtime.exec( deleteCommand );
        process.waitFor();

        return true;
    }

    return false;

}

यदि आप बड़े या जटिल निर्देशिकाओं के साथ काम कर रहे हैं तो बेहतर प्रयास करें।


यह क्रॉस-प्लेटफ़ॉर्म काम करता है ??
OneCricketeer

@ क्रिकेट_007 कौन से प्लेटफॉर्म?
जोशुआ पिंटर

खिड़कियाँ? OpenWrt? बीएसडी?
OneCricketeer

1
@ क्रिकेट_007 निश्चित रूप से विंडोज नहीं है। यह Android और macOS पर परीक्षण और उपयोग किया गया था।
जोशुआ पिंटर

0

अमरूद एक-लाइनर प्रदान करता है MoreFiles.deleteRecursively():।

साझा किए गए कई उदाहरणों के विपरीत, यह प्रतीकात्मक लिंक के लिए खाता है और प्रदान किए गए पथ के बाहर फ़ाइलों को (डिफ़ॉल्ट रूप से) नहीं हटाएगा।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.