Получить расположение развернутого приложения Matlab во время выполнения для Mac и Linux

У меня есть несколько автономных программ Matlab, которым по разным причинам необходим доступ к файлам в каталоге, в котором они находятся (либо для запуска другой программы, либо для чтения там некоторых XML-файлов). У меня есть следующая функция, которая работает в Windows:

function execDir = get_deployed_exec_dir()
% Returns the directory of the currently running executable, if deployed,
% an empty string if not deployed (or if unable to determine the directory)
execDir = '';
if isdeployed
    [status, execDir] = system('path');
    if status == 0
        execDir = char(regexpi(execDir, 'Path=(.*?);', 'tokens', 'once'));
    end
end

Чтобы заставить его работать для Linux и Mac, я решил, что могу заменить system('path') на system('echo $PATH') и изменить регулярное выражение, чтобы оно соответствовало синтаксису Unix, но, в отличие от Windows, каталог текущего исполняемого файла, похоже, не добавляется автоматически в начало переменная пути. Есть ли способ в Matlab получить каталог исполняемого в данный момент исполняемого файла (я знаю, что он есть для сценария, но, похоже, он не работает должным образом при развертывании), или мне следует отредактировать сценарий, который устанавливает MCR перед запуском приложение для установки переменной, которую мой код может прочитать с помощью команды system?

Для конкретности где-то на компьютере пользователя находится папка EXECFOLDER, имеющая структуру:

EXECFOLDER
| exec1
| exec2
| run_exec1.sh
| run_exec2.sh
| data.xml

Я хочу выяснить путь к EXECFOLDER независимо от того, где пользователь запускает run_exec1.sh (сценарий, который устанавливает MCR и вызывает exec1), чтобы exec1 мог читать из data.xml и выполнять exec2.

Резюме попыток:

  • system('echo $PATH'): исполняемый каталог не находится на пути в Mac и Linux
  • matlabroot: расположение MCR
  • pwd: текущая папка пользователя, которая может отличаться от расположения исполняемого файла, когда он запускается с полным путем
  • dbstack: расположение распакованного файла .m
  • which: расположение распакованного файла .m
  • fileattrib: расположение распакованного файла .m

person ackrause    schedule 25.07.2013    source источник
comment
Я не совсем понимаю, что вам нужно. Может ли развернутое приложение Matlab использовать matlabroot? А в каком состоянии pwd при запуске программы? Конечно, есть команды * NIX which и whereis, но они кажутся деспотичными.   -  person horchler    schedule 26.07.2013
comment
В развернутом приложении matlabroot указывает местоположение используемого MCR. pwd дает вам местоположение, в котором находится пользователь в терминале (где они вызвали приложение), но для нашей программы люди, как правило, переходят туда, где находятся их данные, и вызывают программу, используя ее полный путь, поэтому, где на самом деле исполняемые файлы находятся, другое из текущего каталога пользователя. Мне было интересно, есть ли в Matlab способ получить эту информацию без необходимости настраивать переменную среды в сценарии Bash, который вы используете для запуска программы.   -  person ackrause    schedule 26.07.2013
comment
Я не могу это проверить, но думаю, я лучше понимаю, о чем вы спрашиваете. Что касается MCR, развернутые приложения работают как функции M-файлов по отношению к Matlab. В этом случае не могли бы вы вызвать stack = dbstack('-completenames') fullpath = stack.Name, чтобы получить полный путь к текущей запущенной программе? Также можно попробовать which (с флагом '-all') или возможно fileattrib.   -  person horchler    schedule 26.07.2013
comment
dbstack, which и fileattrib все, кажется, дают мне место, где .m файлы распаковываются для запуска MCR, а не их исходное местоположение в исполняемом файле. Я начинаю думать, что это может быть так же хорошо, как и в самом коде Matlab, благодаря тому, как он работает.   -  person ackrause    schedule 27.07.2013
comment
Тогда понятия не имею. Вы можете запустить практически любую команду * NIX с помощью функций system и unix, поэтому вам может потребоваться найти там решение (например, which, whereis и, возможно, даже какая-то форма ps). Вы задавали этот вопрос на MatlabCentral? Это похоже на то, что нужно уметь получить.   -  person horchler    schedule 27.07.2013
comment
Также есть lsof в OS X и некоторые другие формы UNIX и /proc/<PID>/ в Linux, которые могут быть полезны.   -  person horchler    schedule 27.07.2013
comment
Могу действительно использовать некоторые отзывы о существующих ответах, так как мне трудно понять, какой из них заслуживает награды.   -  person Dennis Jaheruddin    schedule 20.01.2015


Ответы (4)


Выполняет ли функция ctfroot то, что вам нужно?

ctfroot - это команда из компилятора MATLAB. Из документации:

root = ctfroot возвращает строку, представляющую собой имя папки, в которой разворачивается развертываемый архив для развернутого приложения.

Вероятно, вы захотите использовать команду ctfroot только внутри блока if isdeployed.

Изменить

Если вам нужно расположение исполняемого файла, а не место, в которое он развернут, вы можете использовать следующую функцию:

function currentDir = getcurrentdir
if isdeployed % Stand-alone mode.
    [status, result] = system('path');
    currentDir = char(regexpi(result, 'Path=(.*?);', 'tokens', 'once'));
else % MATLAB mode.
    currentDir = pwd;
end

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

В качестве альтернативы вы можете создать файл MEX, который будет выполнять аналогичную работу. См. этот MathWorks support, ответьте для получения более подробной информации и для примера файла MEX.

person Sam Roberts    schedule 15.01.2015
comment
Место, где он «расширяется», совпадает с местом, где он находится? И поскольку я не могу проверить это сам: считается ли этот ответ лучше или хуже, чем ответ @janus? - person Dennis Jaheruddin; 19.01.2015
comment
@DennisJaheruddin добавил дополнительную информацию, которая может ответить на ваш вопрос более прямо. - person Sam Roberts; 19.01.2015
comment
Я не могу проверить это сам, но вы имеете в виду, что эта проблема устранена? но, в отличие от Windows, каталог исполняемого в данный момент исполняемого файла не добавляется автоматически в начало переменной пути. - person Dennis Jaheruddin; 19.01.2015
comment
Я бы предпочел быть более уверенным, прежде чем присудить награду, но я думаю, вы заслуживаете сомнения! - person Dennis Jaheruddin; 21.01.2015
comment
Извините, @DennisJaheruddin, вчера у меня не было времени ответить на ваш комментарий. Боюсь, у меня нет удобного доступа к платформе, отличной от Windows, чтобы проверить, работает ли там мое решение (решение getCurrentDir или решение с MEX-файлом). Возможно, ответ Януса предпочтительнее для LInux / Mac, я не знаю. Спасибо за награду, но если вы хотите переназначить ее, не беспокойтесь. - person Sam Roberts; 21.01.2015
comment
Ваше системное ('путь') решение сработало для меня для скомпилированного приложения Windows, спасибо за помощь - person Guy Starbuck; 27.07.2017

Есть ли в этом прогресс?

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

myapp.bat:

set scriptpath=%~d0%~p0
"%scriptpath%%~n0%.exe" --ExecutablePath="%scriptpath%" %*

Или, если вы не хотите, чтобы окно CMD оставалось

myapp.bat:

set scriptpath=%~d0%~p0
start "%~n0" "%scriptpath%%~n0%.exe" --ExecutablePath="%scriptpath%" %*

Bash на самом деле сложнее (см. этот вопрос), но может сработать что-то вроде этого:

myapp.sh

#!/bin/bash
SCRIPTPATH="$( cd "$(dirname "$0")" ; pwd -P )"
"${SCRIPTPATH}/myapp.o" --ExecutablePath="${SCRIPTPATH}" $*
person Janus    schedule 29.11.2013
comment
Поскольку я не могу проверить это сам: считается ли этот ответ лучше или хуже, чем ответ @SamRoberts? - person Dennis Jaheruddin; 19.01.2015

Может вам понадобится:

curr_dir = strrep(which(mfilename('fullpath')),mfilename,'')

который предоставит вам каталог .m файла, который в данный момент запущен.

person BerndGit    schedule 14.01.2015

Mac: чтобы получить местоположение установленного исполняемого файла MyDeployedApplication.app на Mac из самого развернутого приложения, попробуйте следующее:

if isdeployed && ismac
    NameOfDeployedApp = 'MyDeployedApplication'; % do not include the '.app' extension
    [~, result] = system(['top -n100 -l1 | grep ' NameOfDeployedApp ' | awk ''{print $1}''']);
    result=strtrim(result);
    [status, result] = system(['ps xuwww -p ' result ' | tail -n1 | awk ''{print $NF}''']);
    if status==0
        diridx=strfind(result,[NameOfDeployedApp '.app']);
        realpwd=result(1:diridx-2);
    else
        msgbox({'realpwd not set:',result})
    end
else
    realpwd = pwd;
end

В этом решении используются команды терминала «ps», «grep» и «top», предполагается, что у пользователя в данный момент запущен единственный экземпляр MyDeployedApplication.app, и оно было протестировано в ОС MAC Yosemite 10.10. 5 только с MATLAB Compiler 2015a.

Примечание. Хотя pgrep работал, чтобы вернуть PID развернутого, запущенного в данный момент приложения извне приложения (непосредственно в Терминале или в открытом сеансе MATLAB), он ничего не вернул из приложения. Отсюда и использование top и grep.

Linux: чтобы получить путь к установленному исполняемому файлу в Linux, измените синтаксис ответа Сэма на стиль Linux:

[status, result] = system('echo $PATH');
realpwd = char(regexpi(result, '(.*?):', 'tokens', 'once'));        
person Marianne    schedule 11.07.2016
comment
Примечание: я технически не могу ответить на нерешенный вопрос @ dennis-jaheruddin по ответу sam-roberts, поэтому сейчас я помещу его здесь: дополнительное решение в разделе редактирования Сэма работает для Windows, но не работает для Mac, как обнаружил первоначальный вопросник. Это связано с тем, что Mac не добавляет путь к исполняемому файлу в переменную пути при запуске развернутого приложения. Но даже если бы это было так, команда должна была бы быть «echo $ PATH», а не «path», а последующий синтаксический анализ должен был бы использовать двоеточие вместо точки с запятой, поскольку Mac использует точку с запятой в качестве разделителя, как Linux. - person Marianne; 11.07.2016
comment
Дорогая Марианна, а как насчет решения для Windows? - person FabioSpaghetti; 17.05.2020