[prev in list] [next in list] [prev in thread] [next in thread] 

List:       coreutils-bug
Subject:    mv feature request: -z swap files
From:       TL Mieszkowski <tlm () ftfa ! us>
Date:       2009-01-31 21:52:24
Message-ID: 20090131215224.GA24741 () ski ! ath ! cx
[Download RAW message or body]

I've needed to swap two filenames more than once,
but no UNIX program I can find does it. 

The patch I've included works on two regular files,
one regular file and a directory, but if you provide two
directories or 1 directory first it trashes the first directory.  
I think this is due the vagaries of the 
rename function, but I can't understand why it happens.
It says it can't copy a directory into itself, but the target
doesn't even exist.

There may also be issues across filesystems, since
it uses the /tmp directory? Is there a way to do it without
a /tmp? Is it possible to do it right, without just calling 
mv? Is this workable at all?

--- coreutils-git-orig/src/mv.c	2009-01-28 23:32:41.000000000 -0500
+++ coreutils-git/src/mv.c	2009-01-31 15:24:59.362747668 -0500
@@ -69,6 +70,7 @@
   {"target-directory", required_argument, NULL, 't'},
   {"update", no_argument, NULL, 'u'},
   {"verbose", no_argument, NULL, 'v'},
+  {"swap", no_argument, NULL, 'z'},
   {GETOPT_HELP_OPTION_DECL},
   {GETOPT_VERSION_OPTION_DECL},
   {NULL, 0, NULL, 0}
@@ -283,6 +285,7 @@
 Usage: %s [OPTION]... [-T] SOURCE DEST\n\
   or:  %s [OPTION]... SOURCE... DIRECTORY\n\
   or:  %s [OPTION]... -t DIRECTORY SOURCE...\n\
+  or:  %s [OPTION]... -z FILE1 FILE2...\n\
 "),
 	      program_name, program_name, program_name);
       fputs (_("\
@@ -312,6 +315,7 @@
                                  than the destination file or when the\n\
                                  destination file is missing\n\
   -v, --verbose                explain what is being done\n\
+  -z, --swap                swap the names of FILE1 and FILE2\n\
 "), stdout);
       fputs (HELP_OPTION_DESCRIPTION, stdout);
       fputs (VERSION_OPTION_DESCRIPTION, stdout);
@@ -338,6 +342,8 @@
 {
   int c;
   bool ok;
+  bool swap_files = false;
+  char *tmp;
   bool make_backups = false;
   char *backup_suffix_string;
   char *version_control_string = NULL;
@@ -361,7 +367,7 @@
      we'll actually use backup_suffix_string.  */
   backup_suffix_string = getenv ("SIMPLE_BACKUP_SUFFIX");
 
-  while ((c = getopt_long (argc, argv, "bfint:uvS:T", long_options, NULL))
+  while ((c = getopt_long (argc, argv, "bfint:uvzS:T", long_options, NULL))
 	 != -1)
     {
       switch (c)
@@ -410,6 +416,9 @@
 	  make_backups = true;
 	  backup_suffix_string = optarg;
 	  break;
+	case 'z':
+    swap_files = true;    
+	  break;
 	case_GETOPT_HELP_CHAR;
 	case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
 	default:
@@ -430,6 +440,25 @@
       usage (EXIT_FAILURE);
     }
+  
+  if (swap_files)
+  {
+      tmp = tempnam("/tmp/",NULL);
+      if (tmp)
+      {
+          hash_init ();
+          ok = true;
+          ok &= movefile (file[0], tmp, false, &x);
+          ok &= movefile (file[1], file[0], false, &x);
+          ok &= movefile (tmp, file[1], false, &x);
+          exit (ok ? EXIT_SUCCESS : EXIT_FAILURE);
+      }
+      else
+          error (0, 0, _("tempnam error"));
+      exit(EXIT_FAILURE);
+  }
+
   if (no_target_directory)
     {
       if (target_directory)


_______________________________________________
Bug-coreutils mailing list
Bug-coreutils@gnu.org
http://lists.gnu.org/mailman/listinfo/bug-coreutils

[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic