web-dev-qa-db-ja.com

Java 1.6-シンボリックリンクを決定する

DirectoryWalkerクラスで、Fileインスタンスが実際にディレクトリへのシンボリックリンクであるかどうかを確認します(ウォーカーがUNIXシステム上を歩くと仮定)。与えられたインスタンスがディレクトリであることはすでに知っていますが、以下はシンボリックリンクを特定するための信頼できる条件ですか?

File file;
// ...      
if (file.getAbsolutePath().equals(file.getCanonicalPath())) {
    // real directory ---> do normal stuff      
}
else {
    // possible symbolic link ---> do link stuff
}
43
msi

Apache Commonsで使用される手法では、ファイル自体ではなく、親ディレクトリへの正規パスを使用します。不一致の原因がシンボリックリンクであることを保証できるとは思いませんが、ファイルに特別な処理が必要であることを示しています。

これは Apache code (- their license の対象)であり、簡潔にするために変更されています。

public static boolean isSymlink(File file) throws IOException {
  if (file == null)
    throw new NullPointerException("File must not be null");
  File Canon;
  if (file.getParent() == null) {
    Canon = file;
  } else {
    File canonDir = file.getParentFile().getCanonicalFile();
    Canon = new File(canonDir, file.getName());
  }
  return !Canon.getCanonicalFile().equals(Canon.getAbsoluteFile());
}
45
erickson

また、file.isFile()file.isDirectory()はどちらも解決済みファイルに基づいて結果を返すため、falseがシンボリックリンクを参照している場合はどちらもfileを返すことに注意してください。ターゲットは存在しません。

(私はこれがそれ自体有用な答えではないことを知っていますが、それは私に数回つまずきましたので、共有する必要があると思いました)

13
Rob Oxspring

Java 1.6は、ファイルシステムへのそのような低レベルのアクセスを提供しません。 = NIO 2 のように見えます。Java 1.7に含める必要があります。シンボリックリンクがサポートされます。 新しいAPIのドラフト は利用可能です。シンボリックリンク そこに記載されています作成中 および フォロー中 それらは可能です。どの方法を使用して検索するべきか正確にわかりませんファイルがシンボリックリンクであるかどうかを調べるNIO 2について議論するための メーリングリスト があります-おそらく彼らは知っているでしょう。

13
Esko Luontola

getCanonicalPath() は、絶対パスとは異なる可能性のある他のことができるように見えます。

このメソッドは、必要に応じて、getAbsolutePath()メソッドを呼び出すのと同じように、最初にこのパス名を絶対形式に変換し、次にシステムに依存する方法で一意の形式にマップします。これには通常、「。」などの冗長な名前の削除が含まれます。パス名から「..」、シンボリックリンクを解決(UNIXプラットフォームの場合)、ドライブ文字を標準のケースに変換(Microsoft Windowsプラットフォームの場合)。

しかし、大部分のユースケースで機能する可能性があります。あなたのマイレージは異なる場合があります。

5
Michael Myers

* nix用に特別にコーディングしている場合は、Javaから次のようにシェルコマンドを実行できます。

Process p = Runtime.getRuntime().exec(new String[]{"test", "-h", yourFileName});
p.waitFor();
if (p.exitValue() == 0) 
   System.out.println("This file is a symbolic link");
else
   System.out.println("This file is not a symbolic link");

これは* nixに固有のものですが、少なくとも機能します。

3
Beaker

そのような古い投稿に返信して申し訳ありませんが、しばらく前にWindowsシステムの解決策を探していたところ、以前の回答の一部がうまくいかなかった。クロスプラットフォームの互換性を気にせず、Windowsのソリューションだけが必要な場合は、次の方法が私の目的に適しています。

File f = new File("whatever file or folder");
if (f instanceof ShellFolder) {
  ShellFolder sf = (ShellFolder)f;
  if (sf.isLink()) {
    // Your code when it's a link
  }
}
1
Ray Newman