2016-11-03 6 views
0

ディレクトリに壊れたリンクが含まれているかどうかを確認して番号を返すかどうかを確認します。私はコマンドfind -L /dir/* -type d -prune -o -type l | wc -lを使用したいと思うし、それは私の端末で正常に動作します。しかし、私はruntime.exec経由で私のJavaコードでそれを実行すると、エラーがスローされます。Javaコード内でbash cmd "find -L"を呼び出す方法

Unable to call process "find -L /dir/* -type d -prune -o -type l | wc -l ". Cause: find: paths must precede expression: |Usage: find [-H] [-L] [-P] [-Olevel] [-D help|tree|search|stat|rates|opt|exec] [path...] [expression]

私は'/dar/*'"/dir/*"/dir/\*を試してみましたが、それらのどれも機能しません。どんな助けもありがとうございます。

+0

@andlrcの検索:不明な述語 ' -L ' – user2038560

+0

外部コマンドを使用して、Javaコードが実行可能な何かを行うのはなぜですか? – VGR

+0

@VGRこれは古いプロジェクトで、既に多くの外部コマンドを使用しています。コードの一貫性を保ちたい。しかし、私が解決策を見つけることができなければ、私はJavaのプレーンなソリューションに切り替えます。 – user2038560

答えて

0

パイプ演算子(|)は、findコマンドではなく、bashのようなシェルによって提供される機能です。 Runtime.execは、文字列の最初の単語で定義されたコマンドにすべての引数を渡します。この場合はfindです。findコマンドは、そのパイプシンボルが何であるかわかりません。

find -L /dir/* -type d -prune -o -type l \| wc -l 

あなたは|がそう、それはあなたのJavaコードのように、findコマンドに渡され\|のようにエスケープしてやっている通常のターミナルウィンドウでコマンドを実行することによって自分自身のために、この効果を見ることができますが、

一つの一般的な解決策は、bash -c O引数として全体コマンドを渡すことである。

Process process = new ProcessBuilder("bash", "-c", 
    "find -L /dir/* -type d -prune -o -type l | wc -l").start(); 

(のRuntime.execが廃止され、その置換は、よりCLを有するProcessBuilderを、あります早期の行動を定義した)

より良い解決策は、Javaの行をカウントし、完全にパイプ記号を避けるためです:。ProcessBuilderをを個別に引数を渡す

Process process = new ProcessBuilder(
    "find", "-L", "/dir/*", "-type", "d", "-prune", "-o", "-type", "l").start(); 

long brokenLinkCount; 
try (BufferedReader lineReader = 
    new BufferedReader(new InputStreamReader(process.getInputStream()))) { 

    brokenLinkCount = lineReader.lines().count(); 
} 

は、コマンドがのために働くという利点がありますすべてのパス。ファイル名にスペースや引用符が含まれているパスも含まれます。

あなたはこのルートを行くにしたくないと述べているにもかかわらず、最後に、最善のアプローチは、外部コマンドを廃止することで、Javaでそれを行う:

Path dir = Paths.get("/dir"); 

Stream<Path> brokenLinks = 
    Files.find(dir, 1, (path, attr) -> attr.isSymbolicLink()) 
    .filter(path -> { 
     try { 
      return !Files.exists(Files.readSymbolicLink(path)); 
     } catch (IOException e) { 
      System.err.println("Couldn't read link " + path + ": " + e); 
      return false; 
     } 
    }); 
long brokenLinkCount = brokenLinks.count(); 
関連する問題