dirfns.cc

Go to the documentation of this file.
00001 /*
00002 
00003 Copyright (C) 1994-2012 John W. Eaton
00004 
00005 This file is part of Octave.
00006 
00007 Octave is free software; you can redistribute it and/or modify it
00008 under the terms of the GNU General Public License as published by the
00009 Free Software Foundation; either version 3 of the License, or (at your
00010 option) any later version.
00011 
00012 Octave is distributed in the hope that it will be useful, but WITHOUT
00013 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00014 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00015 for more details.
00016 
00017 You should have received a copy of the GNU General Public License
00018 along with Octave; see the file COPYING.  If not, see
00019 <http://www.gnu.org/licenses/>.
00020 
00021 */
00022 
00023 #ifdef HAVE_CONFIG_H
00024 #include <config.h>
00025 #endif
00026 
00027 #include <cerrno>
00028 #include <cstdio>
00029 #include <cstddef>
00030 #include <cstdlib>
00031 #include <cstring>
00032 
00033 #include <sstream>
00034 #include <string>
00035 
00036 #include <sys/types.h>
00037 #include <unistd.h>
00038 
00039 #include "file-ops.h"
00040 #include "file-stat.h"
00041 #include "glob-match.h"
00042 #include "oct-env.h"
00043 #include "pathsearch.h"
00044 #include "str-vec.h"
00045 
00046 #include "Cell.h"
00047 #include "defun.h"
00048 #include "dir-ops.h"
00049 #include "dirfns.h"
00050 #include "error.h"
00051 #include "gripes.h"
00052 #include "input.h"
00053 #include "load-path.h"
00054 #include "oct-obj.h"
00055 #include "pager.h"
00056 #include "procstream.h"
00057 #include "sysdep.h"
00058 #include "toplev.h"
00059 #include "unwind-prot.h"
00060 #include "utils.h"
00061 #include "variables.h"
00062 
00063 // TRUE means we ask for confirmation before recursively removing a
00064 // directory tree.
00065 static bool Vconfirm_recursive_rmdir = true;
00066 
00067 // The time we last time we changed directories.
00068 octave_time Vlast_chdir_time = 0.0;
00069 
00070 static int
00071 octave_change_to_directory (const std::string& newdir)
00072 {
00073   int cd_ok = octave_env::chdir (file_ops::tilde_expand (newdir));
00074 
00075   if (cd_ok)
00076     {
00077       Vlast_chdir_time.stamp ();
00078 
00079       // FIXME -- should this be handled as a list of functions
00080       // to call so users can add their own chdir handlers?
00081 
00082       load_path::update ();
00083     }
00084   else
00085     error ("%s: %s", newdir.c_str (), gnulib::strerror (errno));
00086 
00087   return cd_ok;
00088 }
00089 
00090 DEFUN (cd, args, nargout,
00091   "-*- texinfo -*-\n\
00092 @deftypefn  {Command} {} cd dir\n\
00093 @deftypefnx {Command} {} chdir dir\n\
00094 Change the current working directory to @var{dir}.  If @var{dir} is\n\
00095 omitted, the current directory is changed to the user's home\n\
00096 directory.  For example,\n\
00097 \n\
00098 @example\n\
00099 cd ~/octave\n\
00100 @end example\n\
00101 \n\
00102 @noindent\n\
00103 changes the current working directory to @file{~/octave}.  If the\n\
00104 directory does not exist, an error message is printed and the working\n\
00105 directory is not changed.\n\
00106 @seealso{mkdir, rmdir, dir}\n\
00107 @end deftypefn")
00108 {
00109   octave_value_list retval;
00110 
00111   int argc = args.length () + 1;
00112 
00113   string_vector argv = args.make_argv ("cd");
00114 
00115   if (error_state)
00116     return retval;
00117 
00118   if (argc > 1)
00119     {
00120       std::string dirname = argv[1];
00121 
00122       if (dirname.length () > 0
00123           && ! octave_change_to_directory (dirname))
00124         {
00125           return retval;
00126         }
00127     }
00128   else
00129     {
00130       // Behave like Unixy shells for "cd" by itself, but be Matlab
00131       // compatible if doing "current_dir = cd".
00132 
00133       if (nargout == 0)
00134         {
00135           std::string home_dir = octave_env::get_home_directory ();
00136 
00137           if (home_dir.empty () || ! octave_change_to_directory (home_dir))
00138             return retval;
00139         }
00140       else
00141         retval = octave_value (octave_env::get_current_directory ());
00142     }
00143 
00144   return retval;
00145 }
00146 
00147 DEFALIAS (chdir, cd);
00148 
00149 DEFUN (pwd, , ,
00150   "-*- texinfo -*-\n\
00151 @deftypefn {Built-in Function} {} pwd ()\n\
00152 Return the current working directory.\n\
00153 @seealso{dir, ls}\n\
00154 @end deftypefn")
00155 {
00156   return octave_value (octave_env::get_current_directory ());
00157 }
00158 
00159 DEFUN (readdir, args, ,
00160   "-*- texinfo -*-\n\
00161 @deftypefn {Built-in Function} {[@var{files}, @var{err}, @var{msg}] =} readdir (@var{dir})\n\
00162 Return names of the files in the directory @var{dir} as a cell array of\n\
00163 strings.  If an error occurs, return an empty cell array in @var{files}.\n\
00164 \n\
00165 If successful, @var{err} is 0 and @var{msg} is an empty string.\n\
00166 Otherwise, @var{err} is nonzero and @var{msg} contains a\n\
00167 system-dependent error message.\n\
00168 @seealso{ls, dir, glob}\n\
00169 @end deftypefn")
00170 {
00171   octave_value_list retval;
00172 
00173   retval(2) = std::string ();
00174   retval(1) = -1.0;
00175   retval(0) = Cell ();
00176 
00177   if (args.length () == 1)
00178     {
00179       std::string dirname = args(0).string_value ();
00180 
00181       if (error_state)
00182         gripe_wrong_type_arg ("readdir", args(0));
00183       else
00184         {
00185           dir_entry dir (dirname);
00186 
00187           if (dir)
00188             {
00189               string_vector dirlist = dir.read ();
00190               retval(1) = 0.0;
00191               retval(0) = Cell (dirlist.sort ());
00192             }
00193           else
00194             {
00195               retval(2) = dir.error ();
00196             }
00197         }
00198     }
00199   else
00200     print_usage ();
00201 
00202   return retval;
00203 }
00204 
00205 // FIXME -- should maybe also allow second arg to specify
00206 // mode?  OTOH, that might cause trouble with compatibility later...
00207 
00208 DEFUNX ("mkdir", Fmkdir, args, ,
00209   "-*- texinfo -*-\n\
00210 @deftypefn  {Built-in Function} {[@var{status}, @var{msg}, @var{msgid}] =} mkdir (@var{dir})\n\
00211 @deftypefnx {Built-in Function} {[@var{status}, @var{msg}, @var{msgid}] =} mkdir (@var{parent}, @var{dir})\n\
00212 Create a directory named @var{dir} in the directory @var{parent}.\n\
00213 \n\
00214 If successful, @var{status} is 1, with @var{msg} and @var{msgid} empty\n\
00215 character strings.  Otherwise, @var{status} is 0, @var{msg} contains a\n\
00216 system-dependent error message, and @var{msgid} contains a unique\n\
00217 message identifier.\n\
00218 @seealso{rmdir}\n\
00219 @end deftypefn")
00220 {
00221   octave_value_list retval;
00222 
00223   retval(2) = std::string ();
00224   retval(1) = std::string ();
00225   retval(0) = false;
00226 
00227   int nargin = args.length ();
00228 
00229   std::string dirname;
00230 
00231   if (nargin == 2)
00232     {
00233       std::string parent = args(0).string_value ();
00234       std::string dir = args(1).string_value ();
00235 
00236       if (error_state)
00237         {
00238           gripe_wrong_type_arg ("mkdir", args(0));
00239           return retval;
00240         }
00241       else
00242         dirname = file_ops::concat (parent, dir);
00243     }
00244   else if (nargin == 1)
00245     {
00246       dirname = args(0).string_value ();
00247 
00248       if (error_state)
00249         {
00250           gripe_wrong_type_arg ("mkdir", args(0));
00251           return retval;
00252         }
00253     }
00254 
00255   if (nargin == 1 || nargin == 2)
00256     {
00257       std::string msg;
00258 
00259       dirname = file_ops::tilde_expand (dirname);
00260 
00261       file_stat fs (dirname);
00262 
00263       if (fs && fs.is_dir ())
00264         {
00265           // For compatibility with Matlab, we return true when the
00266           // directory already exists.
00267 
00268           retval(2) = "mkdir";
00269           retval(1) = "directory exists";
00270           retval(0) = true;
00271         }
00272       else
00273         {
00274           int status = octave_mkdir (dirname, 0777, msg);
00275 
00276           if (status < 0)
00277             {
00278               retval(2) = "mkdir";
00279               retval(1) = msg;
00280             }
00281           else
00282             retval(0) = true;
00283         }
00284     }
00285   else
00286     print_usage ();
00287 
00288   return retval;
00289 }
00290 
00291 DEFUNX ("rmdir", Frmdir, args, ,
00292   "-*- texinfo -*-\n\
00293 @deftypefn  {Built-in Function} {[@var{status}, @var{msg}, @var{msgid}] =} rmdir (@var{dir})\n\
00294 @deftypefnx {Built-in Function} {[@var{status}, @var{msg}, @var{msgid}] =} rmdir (@var{dir}, \"s\")\n\
00295 Remove the directory named @var{dir}.\n\
00296 \n\
00297 If successful, @var{status} is 1, with @var{msg} and @var{msgid} empty\n\
00298 character strings.  Otherwise, @var{status} is 0, @var{msg} contains a\n\
00299 system-dependent error message, and @var{msgid} contains a unique\n\
00300 message identifier.\n\
00301 \n\
00302 If the optional second parameter is supplied with value @code{\"s\"},\n\
00303 recursively remove all subdirectories as well.\n\
00304 @seealso{mkdir, confirm_recursive_rmdir}\n\
00305 @end deftypefn")
00306 {
00307   octave_value_list retval;
00308 
00309   retval(2) = std::string ();
00310   retval(1) = std::string ();
00311   retval(0) = false;
00312 
00313   int nargin = args.length ();
00314 
00315   if (nargin == 1 || nargin == 2)
00316     {
00317       std::string dirname = args(0).string_value ();
00318 
00319       if (error_state)
00320         gripe_wrong_type_arg ("rmdir", args(0));
00321       else
00322         {
00323           std::string fulldir = file_ops::tilde_expand (dirname);
00324           int status = -1;
00325           std::string msg;
00326 
00327           if (nargin == 2)
00328             {
00329               if (args(1).string_value () == "s")
00330                 {
00331                   bool doit = true;
00332 
00333                   if (interactive && Vconfirm_recursive_rmdir)
00334                     {
00335                       std::string prompt
00336                         = "remove entire contents of " + fulldir + "? ";
00337 
00338                       doit = octave_yes_or_no (prompt);
00339                     }
00340 
00341                   if (doit)
00342                     status = octave_recursive_rmdir (fulldir, msg);
00343                 }
00344               else
00345                 error ("rmdir: expecting second argument to be \"s\"");
00346             }
00347           else
00348             status = octave_rmdir (fulldir, msg);
00349 
00350           if (status < 0)
00351             {
00352               retval(2) = "rmdir";
00353               retval(1) = msg;
00354             }
00355           else
00356             retval(0) = true;
00357         }
00358     }
00359   else
00360     print_usage ();
00361 
00362   return retval;
00363 }
00364 
00365 DEFUNX ("link", Flink, args, ,
00366   "-*- texinfo -*-\n\
00367 @deftypefn {Built-in Function} {[@var{err}, @var{msg}] =} link (@var{old}, @var{new})\n\
00368 Create a new link (also known as a hard link) to an existing file.\n\
00369 \n\
00370 If successful, @var{err} is 0 and @var{msg} is an empty string.\n\
00371 Otherwise, @var{err} is nonzero and @var{msg} contains a\n\
00372 system-dependent error message.\n\
00373 @seealso{symlink}\n\
00374 @end deftypefn")
00375 {
00376   octave_value_list retval;
00377 
00378   retval(1) = std::string ();
00379   retval(0) = -1.0;
00380 
00381   if (args.length () == 2)
00382     {
00383       std::string from = args(0).string_value ();
00384 
00385       if (error_state)
00386         gripe_wrong_type_arg ("link", args(0));
00387       else
00388         {
00389           std::string to = args(1).string_value ();
00390 
00391           if (error_state)
00392             gripe_wrong_type_arg ("link", args(1));
00393           else
00394             {
00395               std::string msg;
00396 
00397               int status = octave_link (from, to, msg);
00398 
00399               retval(0) = status;
00400 
00401               if (status < 0)
00402                 retval(1) = msg;
00403             }
00404         }
00405     }
00406   else
00407     print_usage ();
00408 
00409   return retval;
00410 }
00411 
00412 DEFUNX ("symlink", Fsymlink, args, ,
00413   "-*- texinfo -*-\n\
00414 @deftypefn {Built-in Function} {[@var{err}, @var{msg}] =} symlink (@var{old}, @var{new})\n\
00415 Create a symbolic link @var{new} which contains the string @var{old}.\n\
00416 \n\
00417 If successful, @var{err} is 0 and @var{msg} is an empty string.\n\
00418 Otherwise, @var{err} is nonzero and @var{msg} contains a\n\
00419 system-dependent error message.\n\
00420 @seealso{link, readlink}\n\
00421 @end deftypefn")
00422 {
00423   octave_value_list retval;
00424 
00425   retval(1) = std::string ();
00426   retval(0) = -1.0;
00427 
00428   if (args.length () == 2)
00429     {
00430       std::string from = args(0).string_value ();
00431 
00432       if (error_state)
00433         gripe_wrong_type_arg ("symlink", args(0));
00434       else
00435         {
00436           std::string to = args(1).string_value ();
00437 
00438           if (error_state)
00439             gripe_wrong_type_arg ("symlink", args(1));
00440           else
00441             {
00442               std::string msg;
00443 
00444               int status = octave_symlink (from, to, msg);
00445 
00446               retval(0) = status;
00447 
00448               if (status < 0)
00449                 retval(1) = msg;
00450             }
00451         }
00452     }
00453   else
00454     print_usage ();
00455 
00456   return retval;
00457 }
00458 
00459 DEFUNX ("readlink", Freadlink, args, ,
00460   "-*- texinfo -*-\n\
00461 @deftypefn {Built-in Function} {[@var{result}, @var{err}, @var{msg}] =} readlink (@var{symlink})\n\
00462 Read the value of the symbolic link @var{symlink}.\n\
00463 \n\
00464 If successful, @var{result} contains the contents of the symbolic link\n\
00465 @var{symlink}, @var{err} is 0 and @var{msg} is an empty string.\n\
00466 Otherwise, @var{err} is nonzero and @var{msg} contains a\n\
00467 system-dependent error message.\n\
00468 @seealso{link, symlink}\n\
00469 @end deftypefn")
00470 {
00471   octave_value_list retval;
00472 
00473   retval(2) = std::string ();
00474   retval(1) = -1.0;
00475   retval(0) = std::string ();
00476 
00477   if (args.length () == 1)
00478     {
00479       std::string symlink = args(0).string_value ();
00480 
00481       if (error_state)
00482         gripe_wrong_type_arg ("readlink", args(0));
00483       else
00484         {
00485           std::string result;
00486           std::string msg;
00487 
00488           int status = octave_readlink (symlink, result, msg);
00489 
00490           if (status < 0)
00491             retval(2) = msg;
00492           retval(1) = status;
00493           retval(0) = result;
00494         }
00495     }
00496   else
00497     print_usage ();
00498 
00499   return retval;
00500 }
00501 
00502 DEFUNX ("rename", Frename, args, ,
00503   "-*- texinfo -*-\n\
00504 @deftypefn {Built-in Function} {[@var{err}, @var{msg}] =} rename (@var{old}, @var{new})\n\
00505 Change the name of file @var{old} to @var{new}.\n\
00506 \n\
00507 If successful, @var{err} is 0 and @var{msg} is an empty string.\n\
00508 Otherwise, @var{err} is nonzero and @var{msg} contains a\n\
00509 system-dependent error message.\n\
00510 @seealso{ls, dir}\n\
00511 @end deftypefn")
00512 {
00513   octave_value_list retval;
00514 
00515   retval(1) = std::string ();
00516   retval(0) = -1.0;
00517 
00518   if (args.length () == 2)
00519     {
00520       std::string from = args(0).string_value ();
00521 
00522       if (error_state)
00523         gripe_wrong_type_arg ("rename", args(0));
00524       else
00525         {
00526           std::string to = args(1).string_value ();
00527 
00528           if (error_state)
00529             gripe_wrong_type_arg ("rename", args(1));
00530           else
00531             {
00532               std::string msg;
00533 
00534               int status = octave_rename (from, to, msg);
00535 
00536               retval(0) = status;
00537 
00538               if (status < 0)
00539                 retval(1) = msg;
00540             }
00541         }
00542     }
00543   else
00544     print_usage ();
00545 
00546   return retval;
00547 }
00548 
00549 DEFUN (glob, args, ,
00550   "-*- texinfo -*-\n\
00551 @deftypefn {Built-in Function} {} glob (@var{pattern})\n\
00552 Given an array of pattern strings (as a char array or a cell array) in\n\
00553 @var{pattern}, return a cell array of file names that match any of\n\
00554 them, or an empty cell array if no patterns match.  The pattern strings are\n\
00555 interpreted as filename globbing patterns (as they are used by Unix shells).\n\
00556 Within a pattern\n\
00557 @table @code\n\
00558 @itemx *\n\
00559 matches any string, including the null string,\n\
00560 @itemx ?\n\
00561 matches any single character, and\n\
00562 \n\
00563 @item [@dots{}]\n\
00564 matches any of the enclosed characters.\n\
00565 @end table\n\
00566 \n\
00567 Tilde expansion\n\
00568 is performed on each of the patterns before looking for matching file\n\
00569 names.  For example:\n\
00570 \n\
00571 @example\n\
00572 ls\n\
00573      @result{}\n\
00574         file1  file2  file3  myfile1 myfile1b\n\
00575 glob (\"*file1\")\n\
00576      @result{}\n\
00577         @{\n\
00578           [1,1] = file1\n\
00579           [2,1] = myfile1\n\
00580         @}\n\
00581 glob (\"myfile?\")\n\
00582      @result{}\n\
00583         @{\n\
00584           [1,1] = myfile1\n\
00585         @}\n\
00586 glob (\"file[12]\")\n\
00587      @result{}\n\
00588         @{\n\
00589           [1,1] = file1\n\
00590           [2,1] = file2\n\
00591         @}\n\
00592 @end example\n\
00593 @seealso{ls, dir, readdir}\n\
00594 @end deftypefn")
00595 {
00596   octave_value retval;
00597 
00598   if (args.length () == 1)
00599     {
00600       string_vector pat = args(0).all_strings ();
00601 
00602       if (error_state)
00603         gripe_wrong_type_arg ("glob", args(0));
00604       else
00605         {
00606           glob_match pattern (file_ops::tilde_expand (pat));
00607 
00608           retval = Cell (pattern.glob ());
00609         }
00610     }
00611   else
00612     print_usage ();
00613 
00614   return retval;
00615 }
00616 
00617 /*
00618 %!test
00619 %!  tmpdir = tmpnam;
00620 %!  filename = {"file1", "file2", "file3", "myfile1", "myfile1b"};
00621 %!  if (mkdir (tmpdir))
00622 %!    cwd = pwd;
00623 %!    cd (tmpdir);
00624 %!    if strcmp (canonicalize_file_name (pwd), ...
00625 %!               canonicalize_file_name (tmpdir))
00626 %!      a = 0;
00627 %!      for n = 1:5
00628 %!        save (filename{n}, "a");
00629 %!      endfor
00630 %!    else
00631 %!      rmdir (tmpdir);
00632 %!      error ("Couldn't change to temporary dir");
00633 %!    endif
00634 %!  else
00635 %!    error ("Couldn't create temporary directory");
00636 %!  endif
00637 %!  result1 = glob ("*file1");
00638 %!  result2 = glob ("myfile?");
00639 %!  result3 = glob ("file[12]");
00640 %!  for n = 1:5
00641 %!    delete (filename{n});
00642 %!  endfor
00643 %!  cd (cwd);
00644 %!  rmdir (tmpdir);
00645 %!  assert (result1, {"file1"; "myfile1"});
00646 %!  assert (result2, {"myfile1"});
00647 %!  assert (result3, {"file1"; "file2"});
00648 */
00649 
00650 DEFUNX ("fnmatch", Ffnmatch, args, ,
00651   "-*- texinfo -*-\n\
00652 @deftypefn {Built-in Function} {} fnmatch (@var{pattern}, @var{string})\n\
00653 Return 1 or zero for each element of @var{string} that matches any of\n\
00654 the elements of the string array @var{pattern}, using the rules of\n\
00655 filename pattern matching.  For example:\n\
00656 \n\
00657 @example\n\
00658 @group\n\
00659 fnmatch (\"a*b\", @{\"ab\"; \"axyzb\"; \"xyzab\"@})\n\
00660      @result{} [ 1; 1; 0 ]\n\
00661 @end group\n\
00662 @end example\n\
00663 @end deftypefn")
00664 {
00665   octave_value retval;
00666 
00667   if (args.length () == 2)
00668     {
00669       string_vector pat = args(0).all_strings ();
00670       string_vector str = args(1).all_strings ();
00671 
00672       if (error_state)
00673         gripe_wrong_type_arg ("fnmatch", args(0));
00674       else
00675         {
00676           glob_match pattern (file_ops::tilde_expand (pat));
00677 
00678           retval = pattern.match (str);
00679         }
00680     }
00681   else
00682     print_usage ();
00683 
00684   return retval;
00685 }
00686 
00687 DEFUN (filesep, args, ,
00688   "-*- texinfo -*-\n\
00689 @deftypefn  {Built-in Function} {} filesep ()\n\
00690 @deftypefnx {Built-in Function} {} filesep ('all')\n\
00691 Return the system-dependent character used to separate directory names.\n\
00692 \n\
00693 If 'all' is given, the function returns all valid file separators in\n\
00694 the form of a string.  The list of file separators is system-dependent.\n\
00695 It is @samp{/} (forward slash) under UNIX or @w{Mac OS X}, @samp{/} and\n\
00696 @samp{\\} (forward and backward slashes) under Windows.\n\
00697 @seealso{pathsep}\n\
00698 @end deftypefn")
00699 {
00700   octave_value retval;
00701 
00702   if (args.length () == 0)
00703     retval = file_ops::dir_sep_str ();
00704   else if (args.length () == 1)
00705     {
00706       std::string s = args(0).string_value ();
00707 
00708       if (! error_state)
00709         {
00710           if (s == "all")
00711             retval = file_ops::dir_sep_chars ();
00712           else
00713             gripe_wrong_type_arg ("filesep", args(0));
00714         }
00715       else
00716         gripe_wrong_type_arg ("filesep", args(0));
00717     }
00718   else
00719     print_usage ();
00720 
00721   return retval;
00722 }
00723 
00724 DEFUN (pathsep, args, nargout,
00725     "-*- texinfo -*-\n\
00726 @deftypefn  {Built-in Function} {@var{val} =} pathsep ()\n\
00727 @deftypefnx {Built-in Function} {@var{old_val} =} pathsep (@var{new_val})\n\
00728 Query or set the character used to separate directories in a path.\n\
00729 @seealso{filesep}\n\
00730 @end deftypefn")
00731 {
00732   octave_value retval;
00733 
00734   int nargin = args.length ();
00735 
00736   if (nargout > 0 || nargin == 0)
00737     retval = dir_path::path_sep_str ();
00738 
00739   if (nargin == 1)
00740     {
00741       std::string sval = args(0).string_value ();
00742 
00743       if (! error_state)
00744         {
00745           switch (sval.length ())
00746             {
00747             case 1:
00748               dir_path::path_sep_char (sval[0]);
00749               break;
00750 
00751             case 0:
00752               dir_path::path_sep_char ('\0');
00753               break;
00754 
00755             default:
00756               error ("pathsep: argument must be a single character");
00757               break;
00758             }
00759         }
00760       else
00761         error ("pathsep: argument must be a single character");
00762     }
00763   else if (nargin > 1)
00764     print_usage ();
00765 
00766   return retval;
00767 }
00768 
00769 DEFUN (confirm_recursive_rmdir, args, nargout,
00770   "-*- texinfo -*-\n\
00771 @deftypefn  {Built-in Function} {@var{val} =} confirm_recursive_rmdir ()\n\
00772 @deftypefnx {Built-in Function} {@var{old_val} =} confirm_recursive_rmdir (@var{new_val})\n\
00773 @deftypefnx {Built-in Function} {} confirm_recursive_rmdir (@var{new_val}, \"local\")\n\
00774 Query or set the internal variable that controls whether Octave\n\
00775 will ask for confirmation before recursively removing a directory tree.\n\
00776 \n\
00777 When called from inside a function with the \"local\" option, the variable is\n\
00778 changed locally for the function and any subroutines it calls.  The original\n\
00779 variable value is restored when exiting the function.\n\
00780 @end deftypefn")
00781 {
00782   return SET_INTERNAL_VARIABLE (confirm_recursive_rmdir);
00783 }
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Defines