如何删除目录中的所有文件,但保留符号链接指向的文件?

时间:2019-05-03 19:02:38

标签: java

已被确定为此处另一个问题的可能重复,事实并非如此。我知道如何删除符号链接和文件。我正在尝试使文件与符号链接关联,但删除其他所有内容。

我的问题:删除7天以上目录中的所有文件,与符号链接关联的文件除外。

问题:已成功删除符号链接,但未删除其余的较旧文件。

详细信息:我正在尝试编写一个简单的Java程序来删除7天以上目录中的所有文件和子文件夹,该目录可以正常工作,但是存在一个问题。如果有符号链接,那么我只需要删除链接并保留链接到的文件。除此之外,其他所有内容都会被删除。我知道我非常接近...如果您有任何建议,请告诉我。目前,我可以删除符号链接,但其他旧文件并没有被删除。这可能是一个简单的逻辑错误,也可能是我以错误的方式来解决问题。预先感谢!


import java.nio.file.Files;
import java.nio.file.Paths;
import java.io.IOException;
import java.util.concurrent.TimeUnit;

public class delcache {

    public static void main(String[] args) throws IOException
    {
        String path1="/home/test/cachetest";
        recursiveDelete(7, path1);
    }

    public static void recursiveDelete(int days, String dirPath) throws IOException {

        long cutOff = System.currentTimeMillis() - (days * 24 * 60 * 60 * 1000);
        Files.list(Paths.get(dirPath))
        .forEach(path -> {
            if (Files.isDirectory(path)) {
                try {
                    recursiveDelete(days, path.toString());
                } catch (IOException e) {
                    // log
                }
            } else {
                try {

                    if (Files.getLastModifiedTime(path).to(TimeUnit.MILLISECONDS) < cutOff) {

                        String pathsave = null;

                        if(Files.isSymbolicLink(path)) {
                            pathsave = path.toRealPath().toString();
                            System.out.println("pathsave: " + pathsave);
                            System.out.println("delete symlink: " + path);
                            Files.delete(path);
                        }


                        if(!(Files.isSymbolicLink(path))) {

                            System.out.println("pathsave: " + pathsave);
                            if(!(path.toString().equals(pathsave))) {
                                System.out.println("not equal so delete file: " + path);
                                Files.delete(path);
                            }



                        }

                        //Files.delete(path);

                    }
                } catch (IOException ex) {
                    // log
                }
            }
        });
    }


}

2 个答案:

答案 0 :(得分:0)

您可以使用此方法:

  1. 使用Process process = Runtime.getRuntime.exec("ls -l")列出目录的所有内容。

  2. 逐行读取InputStream中的process

  3. 如果第一个字符为'd',则该行中的文件为目录。递归。

  4. 如果第一个字符为'-',则删除。

  5. 如果第一个字符为“ l”,则它是符号链接。跳过文件。

您可以从同一行获取文件名。例如,如果该行位于变量'str'中,则文件名为str.split("\\s+")[8]

您还可以将文件名用于所需的其他任何检查。


编辑

使用grep的未经测试的方法:

String getLinkedFile(file) {
// Input: A Symbolic link file
// Output: Name of file pointed to by the symlink

    Process p = Runtime.getRuntime.exec("ls -l | grep -e \"->\"");
    BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));

    while ((line = reader.readLine()) != null) {
        String []tokens = line.split("\\s+");
        String linkFile = tokens[8];
        if(linkFile.equals(file.getName()))
            return tokens[10];
    }
    return null;
}

您可能需要根据文件路径修改此功能。

答案 1 :(得分:0)

您的逻辑有缺陷,String pathsave仅在特定路径的当前循环中仍然存在。当循环到达实际文件时,pathsave始终为null。
如果要保存符号链接路径,则需要具有功能之外的路径列表。即使这样,因为您无法保证任何顺序,它也无法正常工作,您可能会先到达符号链接或先到达文件。

据我所知,您必须首先遍历文件夹以查找所有符号链接,将它们保存到方法可访问的全局List中,然后运行并删除文件。
边注:请注意,如果删除符号链接,则下次运行该功能时,以前具有符号链接的相同文件将被删除

public static void main(String[] args) throws IOException
{
    String path1="/home/test/cachetest";
    List<Path> symlinks = getAllSymLinks(path1);
    recursiveDelete(7, path1, symlinks);
}

public static List<Path> getAllSymLinks(String dirPath) throws IOException {
        List<Path> paths = new ArrayList<>();
        Files.list(Paths.get(dirPath))
        .forEach(path -> {
            if (Files.isDirectory(path)) {
                try {
                    paths.addAll(recursiveDelete(days, path.toString()));
                } catch (IOException e) {
                    // log
                }
            } else {
                try {
                    if(Files.isSymbolicLink(path)) {
                        paths.add(path.toRealPath());
                    }
                } catch (IOException ex) {
                    // log
                }
            }
        });

        return paths;
}

public static void recursiveDelete(int days, String dirPath, List<path> symlinks) throws IOException {
    long cutOff = System.currentTimeMillis() - (days * 24 * 60 * 60 * 1000);
    Files.list(Paths.get(dirPath))
    .forEach(path -> {
        if (Files.isDirectory(path)) {
          try {
              recursiveDelete(days, path.toString(), symlinks);
          } catch (IOException e) {
            // log
          }
        } 
        else {
          try {
            if (Files.getLastModifiedTime(path).to(TimeUnit.MILLISECONDS) < cutOff &&
                !Files.isSymbolicLink(path) &&
                !symlinks.contains(path)) 
            {
                 Files.delete(path);    
            }
          } catch (IOException ex) {
            // log
          }
        }
    });