Перенаправление с помощью Runtime.getRuntime().exec() не работает

Мне нужно выполнить команду из программы. С командной строкой все в порядке, пробовал в терминале, но в программе не работает.

Я добавляю копию из своего кода:

  File dir = new File("videos"); 
  String[] children = dir.list(); 
  if (children == null) { 
   // Either dir does not exist or is not a directory 
   System.out.print("No existe el directorio\n");
   } else { 
    for (int i=0; i<children.length; i++) { 
     // Get filename of file or directory 
     String filename = children[i];

     //Recojo el momento exacto
     System.out.print("\n" +filename);

     Process p = Runtime.getRuntime().exec("exiftool -a -u -g1 -j videos/"+filename+">metadata/"+filename+".json");
    }

Программа должна получить имя всех файлов в папке (имя файла) и извлечь метаданные этих видео, записав их в файлы .json в папке «метаданные».
В чем проблема?


person Blanca Hdez    schedule 28.06.2010    source источник
comment
Кстати, не говорите, что это не работает. Это не дает никому никакой информации для продолжения (хотя в данном случае это сработало). Вместо этого вы должны давать выходные данные/сообщения об ошибках, которые заставили вас думать, что что-то не так. При необходимости вы также должны пояснить, что вы ожидали, и что на самом деле произошло (подчеркнув, где они отличались).   -  person Andrzej Doyle    schedule 28.06.2010


Ответы (2)


Проблема в том, что символ перенаправления (>) представляет собой конструкцию на основе оболочки, а не исполняемый файл. Поэтому, если вы не запускаете эту команду через что-то вроде bash (а это не так), она будет интерпретироваться как символьный аргумент для вашего вызова exiftool.

Если вы хотите, чтобы это работало, у вас есть два варианта:

  1. Заставьте bash сделать это — передайте всю командную строку в качестве аргумента bash -c. Это может потребовать героического побега, хотя в вашем случае это выглядит нормально.
  2. Сделайте перенаправление самостоятельно в Java. Вызовите команду без перенаправленного вывода (т.е. все до знака >), затем прочитайте из потока вывода процесса и запишите все содержимое в соответствующий файл.

Последний подход поначалу кажется более трудоемким, но если учесть, что вам в любом случае нужно всегда читать выходные данные процесса (см. javadocs, второй абзац), на самом деле это очень мало. Вы просто отправляете этот вывод в файл, а не выбрасываете его.

person Andrzej Doyle    schedule 28.06.2010
comment
В качестве общей ссылки на проблемы, связанные с Runtime.exec, я предлагаю древнюю, но все же очень подходящую статью Когда Runtime.exec() не работает. - person Joachim Sauer; 19.10.2012

Если у вас есть Java 7, это проще:

Process p = new ProcessBuilder()
    .command("exiftool", "-a", "-u", "-g1", "-j",
             new File("videos", filename).toString())
    .redirectOutput(new File("metadata", filename + ".json"))
    .start();

Это подпадает под «решение 2», но библиотека времени выполнения позаботится о шаблоне.

person Trejkaz    schedule 24.10.2013