Skip to content

Commit 4b47df7

Browse files
committed
is_exe: java, python optional and much faster
1 parent 75bdf2c commit 4b47df7

File tree

9 files changed

+76
-37
lines changed

9 files changed

+76
-37
lines changed

+stdlib/+java/is_exe.m

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
function y = is_exe(p)
2+
3+
y = isfile(p);
4+
5+
if ispc()
6+
y = y && stdlib.native.has_windows_executable_suffix(p);
7+
end
8+
9+
y = y && javaObject("java.io.File", p).canExecute();
10+
11+
end

+stdlib/+native/is_exe.m

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
function y = is_exe(p)
2+
3+
y = isfile(p);
4+
5+
if ispc()
6+
y = y && stdlib.native.has_windows_executable_suffix(p);
7+
end
8+
9+
if ~y, return, end
10+
11+
12+
if ~isMATLABReleaseOlderThan('R2025a')
13+
14+
if isunix
15+
props = ["UserExecute", "GroupExecute", "OtherExecute"];
16+
else
17+
props = "Readable";
18+
end
19+
20+
t = getPermissions(filePermissions(p), props);
21+
22+
y = any(t{1, :});
23+
24+
else
25+
26+
a = stdlib.native.file_attributes(p);
27+
y = a.UserExecute || a.GroupExecute || a.OtherExecute;
28+
29+
end
30+
31+
end

+stdlib/+native/is_readable.m

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
end
1313

1414
t = getPermissions(filePermissions(p), props);
15-
y = t.Readable;
15+
y = any(t{1, :});
1616

1717
else
1818

+stdlib/+native/is_writable.m

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
end
1313

1414
t = getPermissions(filePermissions(p), props);
15-
y = t.Writable;
15+
y = any(t{1, :});
1616

1717
else
1818
a = stdlib.native.file_attributes(p);

+stdlib/+python/is_exe.m

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
function y = is_exe(p)
2+
3+
y = isfile(p);
4+
5+
if ispc()
6+
y = y && stdlib.native.has_windows_executable_suffix(p);
7+
end
8+
9+
y = y && py.os.access(p, py.os.X_OK);
10+
11+
end

+stdlib/get_permissions.m

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@
5151

5252
if isa(v, "matlab.io.WindowsPermissions") || ispc()
5353

54-
if p(1) == 'r' && has_windows_executable_suffix(f)
54+
if p(1) == 'r' && stdlib.native.has_windows_executable_suffix(f)
5555
p(3) = 'x';
5656
end
5757

+stdlib/is_exe.m

Lines changed: 8 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -2,38 +2,18 @@
22
%
33
% false if not a file
44

5-
function ok = is_exe(p)
5+
function y = is_exe(p)
66
arguments
7-
p string
7+
p {mustBeTextScalar}
88
end
99

10-
ok(size(p)) = false;
11-
12-
i = isfile(p);
13-
14-
if ispc()
15-
i = i & has_windows_executable_suffix(p(i));
16-
end
17-
18-
if ~any(i), return, end
19-
20-
if ~isMATLABReleaseOlderThan('R2025a')
21-
22-
if isunix
23-
props = ["UserExecute", "GroupExecute", "OtherExecute"];
24-
else
25-
props = "Readable";
26-
end
27-
28-
t = getPermissions(filePermissions(p(i)), props);
29-
30-
ok(i) = any(t{:,:}, 2);
31-
10+
% Java or Python are like 100x faster than Matlab native
11+
if stdlib.has_java()
12+
y = stdlib.java.is_exe(p);
13+
elseif stdlib.has_python()
14+
y = stdlib.python.is_exe(p);
3215
else
33-
34-
a = stdlib.native.file_attributes(p);
35-
ok = a.UserExecute || a.GroupExecute || a.OtherExecute;
36-
16+
y = stdlib.native.is_exe(p);
3717
end
3818

3919
end

test/TestIsExe.m

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
properties (TestParameter)
44
p = {{fileparts(mfilename('fullpath')) + "/../Readme.md", false}, {"not-exist", false}}
5+
fun = {@stdlib.is_exe, @stdlib.java.is_exe, @stdlib.python.is_exe, @stdlib.native.is_exe}
56
end
67

78
methods(TestClassSetup)
@@ -13,24 +14,29 @@ function pkg_path(tc)
1314

1415
methods(Test, TestTags="impure")
1516

16-
function test_is_exe(tc, p)
17-
tc.verifyEqual(stdlib.is_exe(p{1}), p{2})
17+
function test_is_exe(tc, p, fun)
18+
is_capable(tc, fun)
19+
20+
tc.verifyEqual(fun(p{1}), p{2})
1821
end
1922

2023

21-
function test_is_exe_dir(tc)
22-
tc.verifyFalse(stdlib.is_exe('.'))
24+
function test_is_exe_dir(tc, fun)
25+
is_capable(tc, fun)
26+
27+
tc.verifyFalse(fun('.'))
2328
end
2429

2530

26-
function test_matlab_exe(tc)
31+
function test_matlab_exe(tc, fun)
32+
is_capable(tc, fun)
2733

2834
f = fullfile(matlabroot, "bin/matlab");
2935
if ispc()
3036
f = f + ".exe";
3137
end
3238

33-
tc.verifyTrue(stdlib.is_exe(f))
39+
tc.verifyTrue(fun(f))
3440
end
3541

3642
end

0 commit comments

Comments
 (0)