########################################################################
##
## Copyright (C) 2004-2022 The Octave Project Developers
##
## See the file COPYRIGHT.md in the top-level directory of this
## distribution or .
##
## This file is part of Octave.
##
## Octave is free software: you can redistribute it and/or modify it
## under the terms of the GNU General Public License as published by
## the Free Software Foundation, either version 3 of the License, or
## (at your option) any later version.
##
## Octave is distributed in the hope that it will be useful, but
## WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
## GNU General Public License for more details.
##
## You should have received a copy of the GNU General Public License
## along with Octave; see the file COPYING. If not, see
## .
##
########################################################################
## -*- texinfo -*-
## @deftypefn {} {} dir
## @deftypefnx {} {} dir (@var{directory})
## @deftypefnx {} {[@var{list}] =} dir (@var{directory})
## Display file listing for directory @var{directory}.
##
## If @var{directory} is not specified then list the present working directory.
##
## If a return value is requested, return a structure array with the fields
##
## @table @asis
## @item name
## File or directory name.
##
## @item folder
## Location of file or directory
##
## @item date
## Timestamp of file modification (string value).
##
## @item bytes
## File size in bytes.
##
## @item isdir
## True if name is a directory.
##
## @item datenum
## Timestamp of file modification as serial date number (double).
##
## @item statinfo
## Information structure returned from @code{stat}.
## @end table
##
## If @var{directory} is a filename, rather than a directory, then return
## information about the named file. @var{directory} may also be a list rather
## than a single directory or file.
##
## @var{directory} is subject to shell expansion if it contains any wildcard
## characters @samp{*}, @samp{?}, @samp{[]}. If these wildcard characters are
## escaped with a backslash @samp{\} (e.g., @samp{\*}) on a POSIX platform,
## then they are not treated as wildcards, but as the corresponding literal
## character. On Windows, it is not possible to escape wildcard characters
## because backslash @samp{\} is treated as a file separator. On Windows, use
## @code{ls} for file or folder names that contain characters that would be
## treated as wildcards by @code{dir}.
##
## Note that for symbolic links, @code{dir} returns information about the
## file that the symbolic link points to rather than the link itself. However,
## if the link points to a nonexistent file, @code{dir} returns information
## about the link.
## @seealso{ls, readdir, glob, what, stat, lstat}
## @end deftypefn
function u = dir(d='', w='', recursive=0)
if (!ischar (d))
print_usage ();
endif
if ~isempty(d)
f = filesep; ## file seperator
if (f == '\')
lineEnding = '\r\n';
else
lineEnding = '\n';
endif
if (recursive == 0)
## check if recursive listing is desired and remove recursive tag from path
recursive=!isempty (strfind (d, '**'));
recursiveProcessingActive=recursive; ## remember recursive processing
if (recursive)
d = strrep (d, '**', ''); ## remove recursive tag in d
endif
## change "wrong" slashes to fit the actual system plattform
if (f == '\')
d(d == '/') = f;
else
d(d == '\') = f;
endif
d = [d(1),strrep(d(2:end),[f,f],f)]; ## //->/, preserve // at the beginning for net drives
d = d(1:end - (d(end) == f)); ## cut last char if its a slash
if ( sum (d == f) > 0) ## check if d is a complex path
i = max (find (d == f)); ## last slash in string
w = d( (i + 1):end); ## ending could be wildcard
else
w = d; ## if it is without slash than take all
endif
if (isempty (strfind (w, '*'))) ## check if the ending is a
w = '*'; ## complete directory or a
else
d = d(1:end - length (w) -1 ); ## wildcard
endif
endif
else
f = '';
w = '*';
endif
## read actual directory files
u = __wglob__ ([d, f, w]);
## add '.' and '..* directory entries if all files are searched
if (w=='*')
u = [[d,f,'.'];[d,f,'..'];u];
endif
## recurse one level deeper if there are directories present
if (recursive > 0)
v = __wglob__ ([d, f, '*', f]); ## list ONLY directories
for i = 1:numel (v)
u = [u;dir(v{i}(1:end - 1),w,recursive + 1)]; ## cut slash at the end of v{i}
endfor
recursive = recursive - 1;
endif
if ( (recursive == 0) && (!isempty (u)) )
if (nargout > 0)
## return the directory as a variable
## mtime is unix time = seconds since 1.1.1970
## datenum is days since 1.1.0000
## there is just a constant time difference, only a + is needed
dt = datenum (1970, 1, 1, 1, 0, 0); ## time difference
n = numel (u);
st = cellfun (@(x) stat (x), u); ## in former dir.m lstat was used => check with linux
b = struct (...
'name', cellfun (@(x) x(max (find (x == f)) + 1:end), u, 'UniformOutput', false),...
'folder', cellfun (@(x) x(1:max (find (x == f)) - 1), u, 'UniformOutput', false),...
'date', mat2cell (datestr ([st.mtime]'./(24 .* 3600) + dt), ones (n, 1)),...
'bytes', {st.size}',...
'isdir', cellfun (@(x) S_ISDIR (x), {st.mode}', 'UniformOutput', false),...
'datenum', num2cell ([st.mtime]'./(24 .* 3600) + dt),...
'statinfo', mat2cell (st, ones (n, 1))...
);
u = b;
else
## print the output
if recursiveProcessingActive
## ... in case of recursive processing at the end of the processing
v=cellfun (@(x) x(1:max (find (x == f)) - 1), u, 'UniformOutput', false); ## get folder list
[v, k] = unique (v); ## eliminate duplicates
v(:, 2) = num2cell (k); ## sort in correct order, like it occured
v = sortrows (v, 2); ## ...
k = cell2mat (v(:, 2)); ## read the indices of the directory jumps into k
k(end + 1) = numel (u) + 1; ## add length of u+1
for i=1:numel(k) - 1 ## print the directories after each other
printf ([lineEnding,'Files Found in: %s',lineEnding,lineEnding], v{i, 1}); % directory header
printf ("%s", list_in_columns ( cellfun (@(x) x(max (find (x == f)) + 1:end), u( k(i):(k(i + 1) - 1) ), 'UniformOutput', false) ) );
endfor
else
# ... in case if linear processing... print just the file list without a header
printf ("%s", list_in_columns ( cellfun (@(x) x(max (find (x == f)) + 1:end), u, 'UniformOutput', false) ) );
endif
clear u ## no u can be given back :) => nargout==0
endif
endif
end