【问题标题】:Why aren't my Windows batch files processing when Java executes them?为什么我的 Windows 批处理文件在 Java 执行时没有得到处理?
【发布时间】:2014-01-27 21:45:12
【问题描述】:

我有 2 个文件夹,每个文件夹包含几十个批处理文件 (*.bat)。

批处理文件包含类似的文本

del /f/q F:\MEDIA\IMAGE99\2010\270\z\4034\123.tif > nul
del /f/q F:\MEDIA\IMAGE99\2010\266\z\3025\456.tif > nul
del /f/q F:\MEDIA\IMAGE99\2010\267\z\3025\789.tif > nul
del /f/q F:\MEDIA\IMAGE99\2010\286\z\9025\101.tif > nul
del /f/q F:\MEDIA\IMAGE99\2010\272\z\6029\112.tif > nul
del /f/q F:\MEDIA\IMAGE99\2010\258\z\4034\134.tif > nul

rmdir /q F:\MEDIA\IMAGE99\2010\270\z\4034
rmdir /q F:\MEDIA\IMAGE99\2010\266\z\3025
rmdir /q F:\MEDIA\IMAGE99\2010\267\z\3025
rmdir /q F:\MEDIA\IMAGE99\2010\286\z\9025
rmdir /q F:\MEDIA\IMAGE99\2010\272\z\6029
rmdir /q F:\MEDIA\IMAGE99\2010\258\z\4034

在Java中,我列出每个文件夹中的每个批处理File,并循环遍历列表,执行每个批处理文件如下:

public static boolean batch(File file) {
    
    boolean handled = false;
    Process process = null;
    try {

        process = Runtime.getRuntime().exec("cmd /c start " + file);
        handled = process.waitFor() == 0;

    } catch (Exception ex) {
        // handling removed for example purposes
    } 
    
    return handled;
}

方法返回后,我删除批处理文件。

问题是,我的批处理文件中没有任何命令运行(我请求删除或删除的文件和文件夹没有运行),Java 进程只是继续并删除批处理文件本身。

批处理文件位于文件夹d:\working\spaced folder\purge\batch_files\

写完后,我怀疑我的问题是我将一个带有空格的文件路径传递给 exec() 方法。

我的怀疑正确吗?如果是这样,我该如何解决?如果不是,可能是什么问题?

既然我已经考虑过了,我将研究Java: Execute /cmd /c start path-with-spaces\program.exe


更新

根据下面的 cmets,我已经更改了我的代码,但现在输出挂在 waitFor() 并且批处理文件没有被处理(我请求删除的文件仍然存在)。

代码:

        String commandString = "cmd /c \"" + file +"\"";
        logger.info("COMMAND " + commandString);
        process = Runtime.getRuntime().exec(commandString);
        logger.info("WAITING FOR " + commandString);
        handled = process.waitFor() == 0;
        logger.info("HANDLED " + commandString + " = " + handled);

输出:

COMMAND : cmd /c "d:\working\spaced folder\purge\deleteBatch\F_140.bat"
WAITING FOR : cmd /c "d:\working\spaced folder\purge\deleteBatch\F_140.bat"

【问题讨论】:

  • 如果您的批处理文件路径中有空格,那么是的,您将使用del c:\foo bar,而它应该是del "c:\foo bar"。在 file 参数周围加上一些引号
  • 您可能不想使用start 命令,因为如果您这样做,调用.waitFor 将不会等待批处理文件完成。
  • 引号的工作似乎较慢,但我没有看到内部批处理调用中的任何文件删除。我会尝试不使用start,因为我认为这可能是问题所在。我最初没有start,但这就是我首先阅读 StackOverflow 以获得答案的结果。 :P
  • 不,现在它只是在处理文件。不知道它走了多远;添加调试。
  • 没有。通过 cmd.exe 删除目录将比在 Java 中快很多倍。 Windows 有一个通配符删除系统调用:Java 没有。 @OP我会摆脱命令中的“开始”。你确实想知道它是否有效,如果你使用'start'就不会。

标签: java windows batch-file cmd


【解决方案1】:

现在输出挂在waitFor()

当您使用 Runtime.exec 从 Java 启动外部进程时,您必须读取该进程产生的任何输出,否则该进程可能会阻塞 (source: JavaDocs for java.lang.Process)。

改用ProcessBuilder,调用redirectErrorStream合并标准输出和错误流,然后从process.getInputStream()读取所有内容,直到到达EOF。只有这样才能安全地拨打waitFor

ProcessBuilder 也将帮助解决空格问题,因为您必须自己将命令行拆分为单个单词

ProcessBuilder pb = new ProcessBuilder("cmd", "/c", file.getAbsolutePath());

【讨论】:

  • 我现在就试试,谢谢。仅供参考,ProcessBuilder pb = new ProcessBuilder("cmd", "/c", file.toString());
  • @JoshDM 如果是java.io.File,那么getAbsolutePathtoString 更安全,因为即使File 本身是相对的,它也会为您提供完整路径。
  • 谢谢。这帮助我解决了这个问题。检查作为答案;所用解决方案的代码发布在单独的答案中。
【解决方案2】:

使用的成功解决方案代码,基于 Ian Roberts 的回答:

使用Apache Commons-IO

package com.stackoverflow.windows;

import java.io.File;
import org.apache.commons.io.IOUtils;
import org.apache.commons.io.output.NullOutputStream;

public class Command {

    private Command() {}

    public static boolean batch(File file) {
    
        boolean handled = false;
        Process process = null;
        ProcessBuilder pb = new ProcessBuilder("cmd", "/c", file.getAbsolutePath());
        pb.redirectErrorStream(true);
    
        try {

            process = pb.start();
            IOUtils.copy(process.getInputStream(), new NullOutputStream());
            handled = process.waitFor() == 0;
            
        } catch (Exception ignore) {
        
            // Only throws an IOException we're trying to avoid anyway, 
            // and an expected InterruptedException 
            // handled will be false
        
        } finally {

            if (process != null) {
        
                IOUtils.closeQuietly(process.getInputStream());
            }           
        }
                
        return handled;
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-07-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多