forked from evodevosys/AroSpotFindingSuite
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathnatsortfiles.m
141 lines (140 loc) · 4.8 KB
/
natsortfiles.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
function [X,ndx] = natsortfiles(X,varargin)
% Alphanumeric / Natural-Order sort of a cell array of filenames/filepaths.
%
% (c) 2016 Stephen Cobeldick
%
% Alphanumeric sort of a cell array of filenames or filepaths: sorts by
% character order and also by the values of any numbers that are within
% the strings. Filenames, file-extensions, and directories (if supplied)
% are split apart and are sorted separately: this ensures that shorter
% filenames sort before longer ones (i.e. just like a dictionary sort).
%
%%% Syntax:
% Y = natsortfiles(X)
% Y = natsortfiles(X,xpr)
% Y = natsortfiles(X,xpr,<options>)
% [Y,ndx] = natsortfiles(X,...)
%
% To sort all of the strings in a cell array use NATSORT (File Exchange 34464).
% To sort the rows of a cell array of strings use NATSORTROWS (File Exchange 47433).
%
% See also NATSORT NATSORTROWS SORT SORTROWS NUM2SIP NUM2BIP CELLSTR REGEXP DIR FILEPARTS FULLFILE FILESEP
%
%% File Dependency %%
%
% NATSORTFILES requires the function NATSORT (File Exchange 34464). The inputs
% <xpr> and <options> are passed directly to NATSORT: see NATSORT for case
% sensitivity, sort direction, numeric substring matching, and other options.
%
%% Explanation %%
%
% Using SORT on filenames will sort any of char(0:45), including the printing
% characters ' !"#$%&''()*+,-', before the file extension separator character '.'.
% Therefore this function splits the name and extension and sorts them separately.
%
% Similarly the file separator character within filepaths can cause longer
% directory names to sort before shorter ones, as char(0:46)<'/' and char(0:91)<'\'.
% NATSORTFILES splits filepaths at each file separator character and sorts
% every level of the directory hierarchy separately, ensuring that shorter
% directory names sort before longer, regardless of the characters in the names.
%
%% Examples %%
%
% A = {'a2.txt', 'a10.txt', 'a1.txt'};
% sort(A) % Wrong numeric order:
% ans = 'a1.txt' 'a10.txt' 'a2.txt'
% natsortfiles(A)
% ans = 'a1.txt' 'a2.txt' 'a10.txt'
%
% B = {'test_new.m'; 'test-old.m'; 'test.m'};
% sort(B) % Note '-' sorts before '.':
% ans =
% 'test-old.m'
% 'test.m'
% 'test_new.m'
% natsortfiles(B) % Shorter names before longer (i.e. a dictionary sort):
% ans =
% 'test.m'
% 'test-old.m'
% 'test_new.m'
%
% C = {'test2.m'; 'test10-old.m'; 'test.m'; 'test10.m'; 'test1.m'};
% sort(C) % Wrong numeric order:
% ans =
% 'test.m'
% 'test1.m'
% 'test10-old.m'
% 'test10.m'
% 'test2.m'
% natsortfiles(C) % Correct numeric order, shorter names before longer:
% ans =
% 'test.m'
% 'test1.m'
% 'test2.m'
% 'test10.m'
% 'test10-old.m'
%
% D = {'A2-old\test.m';'A10\test.m';'A2\test.m';'A1archive.zip';'A1\test.m'};
% sort(D) % Wrong numeric order, and '-' sorts before '\':
% ans =
% 'A10\test.m'
% 'A1\test.m'
% 'A1archive.zip'
% 'A2-old\test.m'
% 'A2\test.m'
% natsortfiles(D) % Shorter names before longer:
% ans =
% 'A1archive.zip'
% 'A1\test.m'
% 'A2\test.m'
% 'A2-old\test.m'
% 'A10\test.m'
%
%% Input and Output Arguments %%
%
% Please see NATSORT for a full description of <xpr> and the <options>.
%
%%% Inputs (*=default):
% X = Cell of Strings, with filenames or filepaths to be sorted.
% xpr = String Token, regular expression to detect numeric substrings, '\d+'*.
% <options> can be supplied in any order and are passed directly to NATSORT.
%
%%% Outputs:
% Y = Cell of Strings, <X> with the filenames sorted according to <options>.
% ndx = Numeric Matrix, same size as <X>. Indices such that Y = X(ndx).
%
% [Y,ndx] = natsortrows(X,*xpr,<options>)
%% Input Wrangling %%
%
assert(iscell(X),'First input <X> must be a cell array.')
tmp = cellfun('isclass',X,'char') & cellfun('size',X,1)<2 & cellfun('ndims',X)<3;
assert(all(tmp(:)),'First input <X> must be a cell array of strings (1xN character).')
%
%% Split and Sort File Names/Paths %%
%
% Split full filepaths into file [path,name,extension]:
[pth,nam,ext] = cellfun(@fileparts,X(:),'UniformOutput',false);
% Split path into {dir,subdir,subsubdir,...}:
%pth = regexp(pth,filesep,'split'); % OS dependent
pth = regexp(pth,'[/\\]','split'); % either / or \
len = cellfun('length',pth);
vec(1:numel(len)) = {''};
%
% Natural-order sort of the file extension, file name, and directory names:
[~,ndx] = natsort(ext,varargin{:});
[~,ind] = natsort(nam(ndx),varargin{:});
ndx = ndx(ind);
for k = max(len):-1:1
idx = len>=k;
vec(~idx) = {''};
vec(idx) = cellfun(@(c)c(k),pth(idx));
[~,ind] = natsort(vec(ndx),varargin{:});
ndx = ndx(ind);
end
%
% Return the sorted array and indices:
ndx = reshape(ndx,size(X));
X = X(ndx);
%
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%natsortfiles