パイプ演算子(|
)は、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();
出典
2016-11-03 20:36:25
VGR
@andlrcの検索:不明な述語 ' -L ' – user2038560
外部コマンドを使用して、Javaコードが実行可能な何かを行うのはなぜですか? – VGR
@VGRこれは古いプロジェクトで、既に多くの外部コマンドを使用しています。コードの一貫性を保ちたい。しかし、私が解決策を見つけることができなければ、私はJavaのプレーンなソリューションに切り替えます。 – user2038560