You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java实现:如何从文件夹中批量或按顺序执行Shell/Bat脚本文件

Batch/Sequential Script Execution from a Folder in Java

Hey there, let's fix that script execution issue you're dealing with! Right now your code is trying to run a single file directly, but to batch-execute scripts from a folder, we need two key pieces: folder traversal to collect valid scripts and proper command wrapping (you can't just pass a file path as a command—you need the right interpreter for the script type, like bash for .sh files or cmd /c for .bat files).

First, let's lean into ProcessBuilder over Runtime.exec—it's more flexible, easier to configure, and avoids common pitfalls like stream blocking that can hang your processes.

Step 1: Traverse the Target Folder to Collect Scripts

First, we'll grab all script files from your target directory. You can filter by file extensions (like .sh, .bat, .py) or any custom rule you need. Here's a modern approach using Java NIO.2:

import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import java.util.stream.Collectors;

public class ScriptExecutor {
    public static void main(String[] args) throws Exception {
        // Replace with your target folder path
        Path scriptFolder = Paths.get("/path/to/your/scripts");
        
        // Collect all valid script files (adjust extensions to match your use case)
        List<Path> scriptFiles = Files.walk(scriptFolder, 1) // 1 = only current directory, no subfolders
                .filter(Files::isRegularFile)
                .filter(path -> {
                    String fileName = path.getFileName().toString().toLowerCase();
                    return fileName.endsWith(".sh") || fileName.endsWith(".bat") || fileName.endsWith(".py");
                })
                .collect(Collectors.toList());
        
        // Choose execution mode: sequential or parallel
        executeScriptsSequentially(scriptFiles);
        // executeScriptsInParallel(scriptFiles);
    }
}

Step 2: Execute Scripts Sequentially

If you need scripts to run one after another (wait for each to finish before starting the next), use this method. It handles OS-specific interpreter logic and prevents process hanging:

private static void executeScriptsSequentially(List<Path> scriptFiles) throws Exception {
    for (Path script : scriptFiles) {
        ProcessBuilder pb = buildProcessBuilderForScript(script);
        System.out.println("Starting script: " + script.getFileName());
        
        Process process = pb.start();
        
        // Critical: Consume input/output streams to avoid process blocking
        // Redirects script output/errors to your console
        process.getInputStream().transferTo(System.out);
        process.getErrorStream().transferTo(System.err);
        
        // Wait for the script to finish and check exit code
        int exitCode = process.waitFor();
        System.out.printf("Script %s completed with exit code: %d%n", script.getFileName(), exitCode);
    }
}

private static ProcessBuilder buildProcessBuilderForScript(Path script) {
    String os = System.getProperty("os.name").toLowerCase();
    ProcessBuilder pb;
    
    if (os.contains("win")) {
        // Windows logic: use cmd for batch files, python for Python scripts
        String fileName = script.getFileName().toString().toLowerCase();
        if (fileName.endsWith(".bat") || fileName.endsWith(".cmd")) {
            pb = new ProcessBuilder("cmd", "/c", script.toString());
        } else if (fileName.endsWith(".py")) {
            pb = new ProcessBuilder("python", script.toString());
        } else {
            throw new IllegalArgumentException("Unsupported script type on Windows: " + script);
        }
    } else {
        // Unix/macOS logic: use bash for shell scripts, python3 for Python scripts
        String fileName = script.getFileName().toString().toLowerCase();
        if (fileName.endsWith(".sh")) {
            pb = new ProcessBuilder("bash", script.toString());
        } else if (fileName.endsWith(".py")) {
            pb = new ProcessBuilder("python3", script.toString());
        } else {
            throw new IllegalArgumentException("Unsupported script type on Unix: " + script);
        }
    }
    
    // Optional: Set working directory to the script's folder (helps with relative paths in scripts)
    pb.directory(script.getParent().toFile());
    return pb;
}

Step 3: Execute Scripts in Parallel (Batch Mode)

If you want to run multiple scripts at the same time, use an ExecutorService to manage threads safely:

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

private static void executeScriptsInParallel(List<Path> scriptFiles) {
    // Adjust thread pool size based on how many concurrent scripts you want
    ExecutorService executor = Executors.newFixedThreadPool(3);
    
    for (Path script : scriptFiles) {
        executor.submit(() -> {
            try {
                ProcessBuilder pb = buildProcessBuilderForScript(script);
                System.out.println("Starting parallel script: " + script.getFileName());
                
                Process process = pb.start();
                process.getInputStream().transferTo(System.out);
                process.getErrorStream().transferTo(System.err);
                
                int exitCode = process.waitFor();
                System.out.printf("Parallel script %s completed with exit code: %d%n", script.getFileName(), exitCode);
            } catch (Exception e) {
                System.err.printf("Failed to run script %s: %s%n", script.getFileName(), e.getMessage());
            }
        });
    }
    
    executor.shutdown();
}

Key Fixes from Your Original Code

  • Your original code passed a file path directly as the command—this fails because the OS needs an interpreter to run the script (e.g., bash for .sh files).
  • We added stream consumption (transferTo) to prevent processes from hanging when stdout/stderr buffers fill up.
  • We handle OS-specific differences to make the code cross-platform.

Important Notes

  • On Unix-like systems, ensure your scripts have execute permissions: chmod +x your-script.sh.
  • Adjust the file extension filter to match the script types you need to run.
  • For long-running scripts, add timeout logic using process.waitFor(long timeout, TimeUnit unit) to avoid infinite waits.

内容的提问来源于stack exchange,提问作者Myst

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 17:27:44