2017-01-17 13 views
2

Предположим, я хочу проверить, действителен ли какой-либо исполняемый файл foo до вызова его его аргументами. Различные способы выполнения этого доступны из командной строки (например, $> hash foo).Проверьте, действителен ли исполняемый файл

Однако, насколько мне известно, модули OCAMl Sys или Unix обеспечивают такую ​​функциональность.

Как можно определить идиоматически механизм, который принимает строку, указывающую исполняемый файл unix, и возвращает bool, указывающий, является ли аргумент исполняемым?

ответ

2

Для этой цели вы можете использовать команду file. file возвращает это для исполняемого файла:

file /bin/ls 

output => ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1]=0x37cdd635587f519989044055623abff939002027, stripped 

Вы можете либо разобрать выход или использовать один из многих параметров командной строки, которые file команды.

2

В дополнение к ответу на кодforester file, есть также привязки к libmagic, которые эффективно дают вам доступ к выходу file без необходимости выкладывания. См. https://github.com/Chris00/ocaml-magic, доступный в opam как magic.

+0

Что вы подразумеваете под «shell out»? –

+0

Вызов внешней программы через оболочку (ex bash, cmd.exe и т. Д.) – hcarty

2

Чтобы проверить, является ли файл исполняемым, я хотел бы использовать разрешение файла - вы можете получить их следующим образом:

let getstat f = (Unix.stat (Filename.basename f)).Unix.st_perm;; 
Printf.printf "%d\n" (getstat ".bashrc");; 
> 644 

Показаны что х флаги установлены.

4

Функция, которая позволяет вам проверить, является ли файл исполняемым или нет, является Unix.access. Если вы хотите дополнительно искать путь, вам понадобятся дополнительные строительные леса, например:

let syspath = String.split_on_char ':' (Sys.getenv "PATH") 

let check_executable path = 
    let open Unix in 
    try 
    access path [ X_OK ]; Some path 
    with _ -> None 

let starts_with s prefix = 
    let open String in 
    let plen = length prefix in 
    length s >= plen && sub s 0 plen = prefix 

let search_path name = 
    if starts_with name "/" || starts_with name "./" || starts_with name "../" 
    then 
    check_executable name 
    else 
    List.fold_left (fun acc dir -> 
     match acc with 
     | Some file -> Some file 
     | None -> 
     check_executable (Filename.concat dir name) 
    ) None syspath 

let main() = 
    Array.iter (fun arg -> 
    match search_path arg with 
    | None -> Printf.printf "%s (Not found)\n" arg 
    | Some file -> Printf.printf "%s -> %s\n" arg file) 
    Array.(sub Sys.argv 1 (length Sys.argv - 1)) 

let() = main()