GNU Octave  4.4.1
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
dirfns.cc
Go to the documentation of this file.
1 /*
2 
3 Copyright (C) 1994-2018 John W. Eaton
4 
5 This file is part of Octave.
6 
7 Octave is free software: you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
11 
12 Octave is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with Octave; see the file COPYING. If not, see
19 <https://www.gnu.org/licenses/>.
20 
21 */
22 
23 #if defined (HAVE_CONFIG_H)
24 # include "config.h"
25 #endif
26 
27 #include <cerrno>
28 #include <cstdio>
29 #include <cstddef>
30 #include <cstdlib>
31 #include <cstring>
32 
33 #include <sstream>
34 #include <string>
35 
36 #include "file-ops.h"
37 #include "file-stat.h"
38 #include "glob-match.h"
39 #include "oct-env.h"
40 #include "oct-glob.h"
41 #include "pathsearch.h"
42 #include "str-vec.h"
43 
44 #include "Cell.h"
45 #include "defun.h"
46 #include "dir-ops.h"
47 #include "dirfns.h"
48 #include "error.h"
49 #include "errwarn.h"
50 #include "input.h"
51 #include "load-path.h"
52 #include "octave.h"
53 #include "octave-link.h"
54 #include "ovl.h"
55 #include "pager.h"
56 #include "procstream.h"
57 #include "sysdep.h"
58 #include "interpreter-private.h"
59 #include "interpreter.h"
60 #include "unwind-prot.h"
61 #include "utils.h"
62 #include "variables.h"
63 
64 // TRUE means we ask for confirmation before recursively removing a
65 // directory tree.
66 static bool Vconfirm_recursive_rmdir = true;
67 
68 // The time we last time we changed directories.
70 
71 static int
73 {
75 
76  int cd_ok = octave::sys::env::chdir (xdir);
77 
78  if (! cd_ok)
79  error ("%s: %s", newdir.c_str (), std::strerror (errno));
80 
82 
83  // FIXME: should these actions be handled as a list of functions
84  // to call so users can add their own chdir handlers?
85 
86  octave::load_path& lp =
87  octave::__get_load_path__ ("octave_change_to_directory");
88 
89  lp.update ();
90 
92 
93  return cd_ok;
94 }
95 
96 DEFUN (cd, args, nargout,
97  doc: /* -*- texinfo -*-
98 @deftypefn {} {} cd @var{dir}
99 @deftypefnx {} {} cd
100 @deftypefnx {} {@var{old_dir} =} cd (@var{dir})
101 @deftypefnx {} {} chdir @dots{}
102 Change the current working directory to @var{dir}.
103 
104 If @var{dir} is omitted, the current directory is changed to the user's home
105 directory (@qcode{"~"}).
106 
107 For example,
108 
109 @example
110 cd ~/octave
111 @end example
112 
113 @noindent
114 changes the current working directory to @file{~/octave}. If the
115 directory does not exist, an error message is printed and the working
116 directory is not changed.
117 
118 @code{chdir} is an alias for @code{cd} and can be used in all of the same
119 calling formats.
120 
121 Compatibility Note: When called with no arguments, @sc{matlab} prints the
122 present working directory rather than changing to the user's home directory.
123 @seealso{pwd, mkdir, rmdir, dir, ls}
124 @end deftypefn */)
125 {
126  int nargin = args.length ();
127 
128  if (nargin > 1)
129  print_usage ();
130 
132 
133  if (nargout > 0)
135 
136  if (nargin == 1)
137  {
138  std::string dirname = args(0).xstring_value ("cd: DIR must be a string");
139 
140  if (! dirname.empty ())
142  }
143  else
144  {
146 
147  if (! home_dir.empty ())
148  octave_change_to_directory (home_dir);
149  }
150 
151  return retval;
152 }
153 
154 DEFALIAS (chdir, cd);
155 
156 DEFUN (pwd, , ,
157  doc: /* -*- texinfo -*-
158 @deftypefn {} {} pwd ()
159 @deftypefnx {} {@var{dir} =} pwd ()
160 Return the current working directory.
161 @seealso{cd, dir, ls, mkdir, rmdir}
162 @end deftypefn */)
163 {
165 }
166 
167 DEFUN (readdir, args, ,
168  doc: /* -*- texinfo -*-
169 @deftypefn {} {@var{files} =} readdir (@var{dir})
170 @deftypefnx {} {[@var{files}, @var{err}, @var{msg}] =} readdir (@var{dir})
171 Return the names of files in the directory @var{dir} as a cell array of
172 strings.
173 
174 If an error occurs, return an empty cell array in @var{files}.
175 If successful, @var{err} is 0 and @var{msg} is an empty string.
176 Otherwise, @var{err} is nonzero and @var{msg} contains a system-dependent
177 error message.
178 @seealso{ls, dir, glob, what}
179 @end deftypefn */)
180 {
181  if (args.length () != 1)
182  print_usage ();
183 
184  std::string dirname = args(0).xstring_value ("readdir: DIR must be a string");
185 
186  octave_value_list retval = ovl (Cell (), -1.0, "");
187 
189 
191 
192  if (dir)
193  {
194  string_vector dirlist = dir.read ();
195  retval(0) = Cell (dirlist.sort ());
196  retval(1) = 0.0;
197  }
198  else
199  retval(2) = dir.error ();
200 
201  return retval;
202 }
203 
204 // FIXME: should maybe also allow second arg to specify mode?
205 // OTOH, that might cause trouble with compatibility later...
206 
207 DEFUN (__mkdir__, args, ,
208  doc: /* -*- texinfo -*-
209 @deftypefn {} {} __mkdir__ (@var{parent}, @var{dir})
210 Internal function called by mkdir.m.
211 @seealso{mkdir, rmdir, pwd, cd, umask}
212 @end deftypefn */)
213 {
214  int nargin = args.length ();
215 
217  print_usage ("mkdir");
218 
220 
221  if (nargin == 2)
222  {
223  std::string parent = args(0).xstring_value ("mkdir: PARENT must be a string");
224  std::string dir = args(1).xstring_value ("mkdir: DIR must be a string");
225 
226  dirname = octave::sys::file_ops::concat (parent, dir);
227  }
228  else if (nargin == 1)
229  dirname = args(0).xstring_value ("mkdir: DIR must be a string");
230 
232 
234 
235  if (fs && fs.is_dir ())
236  {
237  // For Matlab compatibility, return true when directory already exists.
238  return ovl (true, "directory exists", "mkdir");
239  }
240  else
241  {
242  std::string msg;
243 
244  int status = octave::sys::mkdir (dirname, 0777, msg);
245 
246  if (status < 0)
247  return ovl (false, msg, "mkdir");
248  else
249  return ovl (true, "", "");
250  }
251 }
252 
253 DEFUNX ("rmdir", Frmdir, args, ,
254  doc: /* -*- texinfo -*-
255 @deftypefn {} {} rmdir @var{dir}
256 @deftypefnx {} {} rmdir (@var{dir}, "s")
257 @deftypefnx {} {[@var{status}, @var{msg}, @var{msgid}] =} rmdir (@dots{})
258 Remove the directory named @var{dir}.
259 
260 If the optional second parameter is supplied with value @qcode{"s"},
261 recursively remove all subdirectories as well.
262 
263 If successful, @var{status} is 1, and @var{msg}, @var{msgid} are empty
264 character strings (""). Otherwise, @var{status} is 0, @var{msg} contains a
265 system-dependent error message, and @var{msgid} contains a unique message
266 identifier.
267 
268 @seealso{mkdir, confirm_recursive_rmdir, pwd}
269 @end deftypefn */)
270 {
271  int nargin = args.length ();
272 
274  print_usage ();
275 
276  std::string dirname = args(0).xstring_value ("rmdir: DIR must be a string");
277 
279  int status = -1;
280  std::string msg;
281 
282  if (nargin == 2)
283  {
284  if (args(1).string_value () != "s")
285  error (R"(rmdir: second argument must be "s" for recursive removal)");
286 
287  bool doit = true;
288 
289  if (octave::application::interactive ()
290  && ! octave::application::forced_interactive ()
292  {
293  std::string prompt = "remove entire contents of " + fulldir + "? ";
294 
295  doit = octave_yes_or_no (prompt);
296  }
297 
298  if (doit)
299  status = octave::sys::recursive_rmdir (fulldir, msg);
300  }
301  else
302  status = octave::sys::rmdir (fulldir, msg);
303 
304  if (status < 0)
305  return ovl (false, msg, "rmdir");
306  else
307  return ovl (true, "", "");
308 }
309 
310 DEFUNX ("link", Flink, args, ,
311  doc: /* -*- texinfo -*-
312 @deftypefn {} {} link @var{old} @var{new}
313 @deftypefnx {} {[@var{err}, @var{msg}] =} link (@var{old}, @var{new})
314 Create a new link (also known as a hard link) to an existing file.
315 
316 If successful, @var{err} is 0 and @var{msg} is an empty string.
317 Otherwise, @var{err} is nonzero and @var{msg} contains a system-dependent
318 error message.
319 @seealso{symlink, unlink, readlink, lstat}
320 @end deftypefn */)
321 {
322  if (args.length () != 2)
323  print_usage ();
324 
325  std::string from = args(0).xstring_value ("link: OLD must be a string");
326  std::string to = args(1).xstring_value ("link: NEW must be a string");
327 
330 
331  std::string msg;
332 
333  int status = octave::sys::link (from, to, msg);
334 
335  if (status < 0)
336  return ovl (-1.0, msg);
337  else
338  return ovl (status, "");
339 }
340 
341 DEFUNX ("symlink", Fsymlink, args, ,
342  doc: /* -*- texinfo -*-
343 @deftypefn {} {} symlink @var{old} @var{new}
344 @deftypefnx {} {[@var{err}, @var{msg}] =} symlink (@var{old}, @var{new})
345 Create a symbolic link @var{new} which contains the string @var{old}.
346 
347 If successful, @var{err} is 0 and @var{msg} is an empty string.
348 Otherwise, @var{err} is nonzero and @var{msg} contains a system-dependent
349 error message.
350 @seealso{link, unlink, readlink, lstat}
351 @end deftypefn */)
352 {
353  if (args.length () != 2)
354  print_usage ();
355 
356  std::string from = args(0).xstring_value ("symlink: OLD must be a string");
357  std::string to = args(1).xstring_value ("symlink: NEW must be a string");
358 
361 
362  std::string msg;
363 
364  int status = octave::sys::symlink (from, to, msg);
365 
366  if (status < 0)
367  return ovl (-1.0, msg);
368  else
369  return ovl (status, "");
370 }
371 
372 DEFUNX ("readlink", Freadlink, args, ,
373  doc: /* -*- texinfo -*-
374 @deftypefn {} {} readlink @var{symlink}
375 @deftypefnx {} {[@var{result}, @var{err}, @var{msg}] =} readlink (@var{symlink})
376 Read the value of the symbolic link @var{symlink}.
377 
378 If successful, @var{result} contains the contents of the symbolic link
379 @var{symlink}, @var{err} is 0, and @var{msg} is an empty string.
380 Otherwise, @var{err} is nonzero and @var{msg} contains a system-dependent
381 error message.
382 @seealso{lstat, symlink, link, unlink, delete}
383 @end deftypefn */)
384 {
385  if (args.length () != 1)
386  print_usage ();
387 
388  std::string symlink = args(0).xstring_value ("readlink: SYMLINK must be a string");
389 
391 
392  std::string result, msg;
393 
394  int status = octave::sys::readlink (symlink, result, msg);
395 
396  if (status < 0)
397  return ovl ("", -1.0, msg);
398  else
399  return ovl (result, status, "");
400 }
401 
402 DEFUNX ("rename", Frename, args, ,
403  doc: /* -*- texinfo -*-
404 @deftypefn {} {} rename @var{old} @var{new}
405 @deftypefnx {} {[@var{err}, @var{msg}] =} rename (@var{old}, @var{new})
406 Change the name of file @var{old} to @var{new}.
407 
408 If successful, @var{err} is 0 and @var{msg} is an empty string.
409 Otherwise, @var{err} is nonzero and @var{msg} contains a system-dependent
410 error message.
411 @seealso{movefile, copyfile, ls, dir}
412 @end deftypefn */)
413 {
414  if (args.length () != 2)
415  print_usage ();
416 
417  std::string from = args(0).xstring_value ("rename: OLD must be a string");
418  std::string to = args(1).xstring_value ("rename: NEW must be a string");
419 
422 
423  std::string msg;
424 
425  int status = octave::sys::rename (from, to, msg);
426 
427  if (status < 0)
428  return ovl (-1.0, msg);
429  else
430  return ovl (status, "");
431 }
432 
433 DEFUN (glob, args, ,
434  doc: /* -*- texinfo -*-
435 @deftypefn {} {} glob (@var{pattern})
436 Given an array of pattern strings (as a char array or a cell array) in
437 @var{pattern}, return a cell array of filenames that match any of
438 them, or an empty cell array if no patterns match.
439 
440 The pattern strings are interpreted as filename globbing patterns (as they
441 are used by Unix shells).
442 
443 Within a pattern
444 
445 @table @code
446 @item *
447 matches any string, including the null string,
448 
449 @item ?
450 matches any single character, and
451 
452 @item [@dots{}]
453 matches any of the enclosed characters.
454 @end table
455 
456 Tilde expansion is performed on each of the patterns before looking for
457 matching filenames. For example:
458 
459 @example
460 ls
461  @result{}
462  file1 file2 file3 myfile1 myfile1b
463 glob ("*file1")
464  @result{}
465  @{
466  [1,1] = file1
467  [2,1] = myfile1
468  @}
469 glob ("myfile?")
470  @result{}
471  @{
472  [1,1] = myfile1
473  @}
474 glob ("file[12]")
475  @result{}
476  @{
477  [1,1] = file1
478  [2,1] = file2
479  @}
480 @end example
481 @seealso{ls, dir, readdir, what}
482 @end deftypefn */)
483 {
484  if (args.length () != 1)
485  print_usage ();
486 
487  string_vector pat = args(0).xstring_vector_value ("glob: PATTERN must be a string");
488 
490 
491  return ovl (Cell (pattern.glob ()));
492 }
493 
494 
495 DEFUN (__wglob__, args, ,
496  doc: /* -*- texinfo -*-
497 @deftypefn {} {} __wglob__ (@var{pattern})
498 Windows-like glob for dir.
499 
500 Given an array of pattern strings (as a char array or a cell array) in
501 @var{pattern}, return a cell array of filenames that match any of
502 them, or an empty cell array if no patterns match.
503 
504 The pattern strings are interpreted as filename globbing patterns
505 (roughly as they are used by Windows dir).
506 
507 Within a pattern
508 
509 @table @code
510 @item *
511 matches any string, including the null string,
512 
513 @item ?
514 matches any single character, and
515 
516 @item *.*
517 matches any string, even if no . is present.
518 @end table
519 
520 Tilde expansion is performed on each of the patterns before looking for
521 matching filenames. For example:
522 
523 @example
524 ls
525  @result{}
526  file1 file2 file3 myfile1 myfile1b
527 glob ("*file1")
528  @result{}
529  @{
530  [1,1] = file1
531  [2,1] = myfile1
532  @}
533 glob ("myfile?")
534  @result{}
535  @{
536  [1,1] = myfile1
537  @}
538 glob ("*.*")
539  @result{}
540  @{
541  [1,1] = file1
542  [2,1] = file2
543  [3,1] = file3
544  [4,1] = myfile1
545  [5,1] = myfile1b
546  @}
547 @end example
548 @seealso{glob, dir}
549 @end deftypefn */)
550 {
551  if (args.length () == 0)
552  return ovl ();
553 
554  string_vector pat = args(0).string_vector_value ();
555 
557 
559 }
560 
561 /*
562 %!test
563 %! tmpdir = tempname;
564 %! filename = {"file1", "file2", "file3", "myfile1", "myfile1b"};
565 %! if (mkdir (tmpdir))
566 %! cwd = pwd;
567 %! cd (tmpdir);
568 %! if (strcmp (canonicalize_file_name (pwd), canonicalize_file_name (tmpdir)))
569 %! a = 0;
570 %! for n = 1:5
571 %! save (filename{n}, "a");
572 %! endfor
573 %! else
574 %! rmdir (tmpdir);
575 %! error ("Couldn't change to temporary dir");
576 %! endif
577 %! else
578 %! error ("Couldn't create temporary directory");
579 %! endif
580 %! result1 = glob ("*file1");
581 %! result2 = glob ("myfile?");
582 %! result3 = glob ("file[12]");
583 %! for n = 1:5
584 %! delete (filename{n});
585 %! endfor
586 %! cd (cwd);
587 %! rmdir (tmpdir);
588 %! assert (result1, {"file1"; "myfile1"});
589 %! assert (result2, {"myfile1"});
590 %! assert (result3, {"file1"; "file2"});
591 */
592 
593 DEFUN (__fnmatch__, args, ,
594  doc: /* -*- texinfo -*-
595 @deftypefn {} {} fnmatch (@var{pattern}, @var{string})
596 Return true or false for each element of @var{string} that matches any of
597 the elements of the string array @var{pattern}, using the rules of
598 filename pattern matching.
599 
600 For example:
601 
602 @example
603 @group
604 fnmatch ("a*b", @{"ab"; "axyzb"; "xyzab"@})
605  @result{} [ 1; 1; 0 ]
606 @end group
607 @end example
608 @seealso{glob, regexp}
609 @end deftypefn */)
610 {
611  if (args.length () != 2)
612  print_usage ();
613 
614  string_vector pat = args(0).string_vector_value ();
615  string_vector str = args(1).string_vector_value ();
616 
618 
619  return ovl (pattern.match (str));
620 }
621 
622 DEFUN (filesep, args, ,
623  doc: /* -*- texinfo -*-
624 @deftypefn {} {} filesep ()
625 @deftypefnx {} {} filesep ("all")
626 Return the system-dependent character used to separate directory names.
627 
628 If @qcode{"all"} is given, the function returns all valid file separators
629 in the form of a string. The list of file separators is system-dependent.
630 It is @samp{/} (forward slash) under UNIX or @w{Mac OS X}, @samp{/} and
631 @samp{\} (forward and backward slashes) under Windows.
632 @seealso{pathsep}
633 @end deftypefn */)
634 {
635  int nargin = args.length ();
636 
637  if (nargin > 1)
638  print_usage ();
639 
641 
642  if (nargin == 0)
644  else
645  {
646  std::string s = args(0).xstring_value ("filesep: argument must be a string");
647  if (s != "all")
648  error (R"(filesep: argument must be "all")");
649 
651  }
652 
653  return retval;
654 }
655 
656 DEFUN (pathsep, args, ,
657  doc: /* -*- texinfo -*-
658 @deftypefn {} {@var{val} =} pathsep ()
659 Query the character used to separate directories in a path.
660 @seealso{filesep}
661 @end deftypefn */)
662 {
663  int nargin = args.length ();
664 
665  if (nargin > 0)
666  print_usage ();
667 
669 }
670 
671 DEFUN (confirm_recursive_rmdir, args, nargout,
672  doc: /* -*- texinfo -*-
673 @deftypefn {} {@var{val} =} confirm_recursive_rmdir ()
674 @deftypefnx {} {@var{old_val} =} confirm_recursive_rmdir (@var{new_val})
675 @deftypefnx {} {} confirm_recursive_rmdir (@var{new_val}, "local")
676 Query or set the internal variable that controls whether Octave
677 will ask for confirmation before recursively removing a directory tree.
678 
679 When called from inside a function with the @qcode{"local"} option, the
680 variable is changed locally for the function and any subroutines it calls.
681 The original variable value is restored when exiting the function.
682 @seealso{rmdir}
683 @end deftypefn */)
684 {
685  return SET_INTERNAL_VARIABLE (confirm_recursive_rmdir);
686 }
static std::string get_current_directory(void)
Definition: oct-env.cc:136
Definition: Cell.h:37
static bool chdir(const std::string &newdir)
Definition: oct-env.cc:256
OCTINTERP_API void print_usage(void)
Definition: defun.cc:54
std::string dir_sep_chars(void)
Definition: file-ops.cc:242
int symlink(const std::string &old_name, const std::string &new_name)
Definition: file-ops.cc:451
static int octave_change_to_directory(const std::string &newdir)
Definition: dirfns.cc:72
static std::string path_sep_str(void)
Definition: pathsearch.cc:127
std::string tilde_expand(const std::string &name)
Definition: file-ops.cc:276
#define DEFUN(name, args_name, nargout_name, doc)
Macro to define a builtin function.
Definition: defun.h:53
void error(const char *fmt,...)
Definition: error.cc:578
#define SET_INTERNAL_VARIABLE(NM)
Definition: variables.h:109
std::string dirname(const std::string &path)
Definition: file-ops.cc:353
Definition: dir-ops.h:36
s
Definition: file-io.cc:2729
static bool Vconfirm_recursive_rmdir
Definition: dirfns.cc:66
bool is_dir(void) const
Definition: file-stat.cc:57
std::string dir_sep_str(void)
Definition: file-ops.cc:233
int recursive_rmdir(const std::string &name)
Definition: file-ops.cc:540
int rename(const std::string &from, const std::string &to)
Definition: file-ops.cc:498
string_vector read(void)
Definition: dir-ops.cc:70
#define DEFALIAS(alias, name)
Macro to define an alias for another existing function name.
Definition: defun.h:211
std::string concat(const std::string &dir, const std::string &file)
Definition: file-ops.cc:344
string_vector windows_glob(const string_vector &pat)
Definition: oct-glob.cc:146
OCTAVE_EXPORT octave_value_list return the number of command line arguments passed to Octave If called with the optional argument the function xample nargout(@histc)
Definition: ov-usr-fcn.cc:997
static std::string get_home_directory(void)
Definition: oct-env.cc:143
int link(const std::string &old_name, const std::string &new_name)
Definition: file-ops.cc:430
std::string str
Definition: hash.cc:118
#define DEFUNX(name, fname, args_name, nargout_name, doc)
Macro to define a builtin function with certain internal name.
Definition: defun.h:82
octave_value retval
Definition: data.cc:6246
string_vector & sort(bool make_uniq=false)
Definition: str-vec.cc:74
is longer than or if then or only for unique occurrences of the complete pattern(false). The default is true. If a cell array of strings ar
Definition: strfind.cc:190
void update(void) const
Definition: load-path.cc:363
load_path & __get_load_path__(const std::string &who)
octave::sys::time Vlast_chdir_time
Definition: dirfns.cc:69
With real return the complex result
Definition: data.cc:3260
return octave_value(v1.char_array_value() . concat(v2.char_array_value(), ra_idx),((a1.is_sq_string()||a2.is_sq_string()) ? '\'' :'"'))
int mkdir(const std::string &nm, mode_t md)
Definition: file-ops.cc:394
bool octave_yes_or_no(const std::string &prompt)
int rmdir(const std::string &name)
Definition: file-ops.cc:518
OCTAVE_EXPORT octave_value_list isa nd deftypefn *return ovl(args(0).isinteger())
int chdir(const std::string &path_arg)
Definition: lo-sysdep.cc:59
std::string error(void) const
Definition: dir-ops.h:77
int readlink(const std::string &path, std::string &result)
Definition: file-ops.cc:472
octave::sys::file_stat fs(filename)
args.length() nargin
Definition: file-io.cc:589
void stamp(void)
Definition: oct-time.cc:106
If this string is the system will ring the terminal sometimes it is useful to be able to print the original representation of the string
Definition: utils.cc:888
string_vector glob(const string_vector &pat)
Definition: oct-glob.cc:70