]> git.ipfire.org Git - thirdparty/coreutils.git/commitdiff
cp,mv: issue "skipped" messages when skipping files
authorPádraig Brady <P@draigBrady.com>
Fri, 7 Apr 2023 09:25:41 +0000 (10:25 +0100)
committerPádraig Brady <P@draigBrady.com>
Sat, 8 Apr 2023 11:11:58 +0000 (12:11 +0100)
* NEWS: Mention the change in behavior to issue a "not replaced"
error diagnostic with -n, and the "skipped" message with -v.
* src/copy.c (copy_internal): Adjust to output the "skipped" messages
depending on -i, -n, -u.
* tests/cp/cp-i.sh: Adjust accordingly.
* tests/mv/mv-n.sh: Likewise.

NEWS
src/copy.c
tests/cp/cp-i.sh
tests/mv/mv-n.sh

diff --git a/NEWS b/NEWS
index e4ed291b4db7d993418f2b9b3a14baa1d4363724..09dba0b80546d278acdd2646caed1f6bfede6481 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -27,6 +27,13 @@ GNU coreutils NEWS                                    -*- outline -*-
   wc will now diagnose if any total counts have overflowed.
   [This bug was present in "the beginning".]
 
+** Changes in behavior
+
+  'cp -n' and 'mv -n' now issue an error diagnostic if skipping a file,
+  to correspond with -n inducing a nonzero exit status as of coreutils 9.2.
+  Similarly 'cp -v' and 'mv -v' will output a message for each file skipped
+  due to -n, -i, or -u.
+
 ** New features
 
   cp and mv now support --update=none to always skip existing files
index e7e14c1502696e5687d5db3c2b7e47f06f726927..0476d95cabee9c2b7689e0b8781b0c89d5bfff7a 100644 (file)
@@ -2333,6 +2333,8 @@ copy_internal (char const *src_name, char const *dst_name,
       if (rename_errno == EEXIST)
         {
           bool return_now = false;
+          bool return_val = true;
+          bool skipped = false;
 
           if ((x->interactive != I_ALWAYS_NO && x->interactive != I_ALWAYS_SKIP)
               && ! same_file_ok (src_name, &src_sb, dst_dirfd, drelname,
@@ -2385,7 +2387,8 @@ copy_internal (char const *src_name, char const *dst_name,
                         }
                     }
 
-                  return true;
+                  skipped = true;
+                  goto skip;
                 }
             }
 
@@ -2404,7 +2407,9 @@ copy_internal (char const *src_name, char const *dst_name,
                      doesn't end up removing the source file.  */
                   if (rename_succeeded)
                     *rename_succeeded = true;
-                  return x->interactive == I_ALWAYS_SKIP;
+
+                  skipped = true;
+                  return_val = x->interactive == I_ALWAYS_SKIP;
                 }
             }
           else
@@ -2415,11 +2420,25 @@ copy_internal (char const *src_name, char const *dst_name,
                       || (x->interactive == I_ASK_USER
                           && ! overwrite_ok (x, dst_name, dst_dirfd,
                                              dst_relname, &dst_sb))))
-                return x->interactive == I_ALWAYS_SKIP;
+                {
+                  skipped = true;
+                  return_val = x->interactive == I_ALWAYS_SKIP;
+                }
+            }
+
+skip:
+          if (skipped)
+            {
+              if (x->verbose)
+                printf (_("skipped %s\n"), quoteaf (dst_name));
+              else if (x->interactive == I_ALWAYS_NO)
+                error (0, 0, _("not replacing %s"), quoteaf (dst_name));
+
+              return_now = true;
             }
 
           if (return_now)
-            return true;
+            return return_val;
 
           if (!S_ISDIR (dst_sb.st_mode))
             {
index b137bc4a5562ab71736691f4004047c79c6fe843..4458b2edd62e61edf28aba42a5bf2fe0fe6a7a2b 100755 (executable)
@@ -28,12 +28,14 @@ echo n | returns_ 1 cp -iR a b 2>/dev/null || fail=1
 
 # test miscellaneous combinations of -f -i -n parameters
 touch c d || framework_failure_
-echo "'c' -> 'd'" > out_copy
-> out_empty
+echo "'c' -> 'd'" > out_copy || framework_failure_
+echo "skipped 'd'" > out_skip || framework_failure_
+echo "cp: not replacing 'd'" > err_skip || framework_failure_
+touch out_empty || framework_failure_
 
 # ask for overwrite, answer no
 echo n | returns_ 1 cp -vi  c d 2>/dev/null > out1 || fail=1
-compare out1 out_empty || fail=1
+compare out1 out_skip || fail=1
 
 # ask for overwrite, answer yes
 echo y | cp -vi  c d 2>/dev/null > out2 || fail=1
@@ -45,6 +47,11 @@ compare out3 out_copy  || fail=1
 
 # -n wins over -i
 echo y | returns_ 1 cp -vin c d 2>/dev/null > out4 || fail=1
+compare out4 out_skip || fail=1
+
+# -n wins over -i non verbose
+echo y | returns_ 1 cp -in c d 2>err4 > out4 || fail=1
+compare err4 err_skip || fail=1
 compare out4 out_empty || fail=1
 
 # ask for overwrite, answer yes
@@ -53,11 +60,11 @@ compare out5 out_copy  || fail=1
 
 # do not ask, prevent from overwrite
 echo n | returns_ 1 cp -vfn c d 2>/dev/null > out6 || fail=1
-compare out6 out_empty || fail=1
+compare out6 out_skip || fail=1
 
 # do not ask, prevent from overwrite
 echo n | returns_ 1 cp -vnf c d 2>/dev/null > out7 || fail=1
-compare out7 out_empty || fail=1
+compare out7 out_skip || fail=1
 
 # options --backup and --no-clobber are mutually exclusive
 returns_ 1 cp -bn c d 2>/dev/null || fail=1
index fbf571368dc65fa04e29c4f2ec403640e5887d94..45d74eb9381c9afce12f6215207e48b67118b7d9 100755 (executable)
@@ -23,12 +23,14 @@ print_ver_ mv
 # test miscellaneous combinations of -f -i -n parameters
 touch a b || framework_failure_
 echo "renamed 'a' -> 'b'" > out_move
+echo "skipped 'b'" > out_skip || framework_failure_
+echo "mv: not replacing 'b'" > err_skip || framework_failure_
 > out_empty
 
 # ask for overwrite, answer no
 touch a b || framework_failure_
 echo n | returns_ 1 mv -vi a b 2>/dev/null > out1 || fail=1
-compare out1 out_empty || fail=1
+compare out1 out_skip || fail=1
 
 # ask for overwrite, answer yes
 touch a b || framework_failure_
@@ -38,17 +40,23 @@ compare out2 out_move || fail=1
 # -n wins (as the last option)
 touch a b || framework_failure_
 echo y | returns_ 1 mv -vin a b 2>/dev/null > out3 || fail=1
+compare out3 out_skip || fail=1
+
+# -n wins (non verbose)
+touch a b || framework_failure_
+echo y | returns_ 1 mv -in a b 2>err3 > out3 || fail=1
 compare out3 out_empty || fail=1
+compare err3 err_skip || fail=1
 
 # -n wins (as the last option)
 touch a b || framework_failure_
 echo y | returns_ 1 mv -vfn a b 2>/dev/null > out4 || fail=1
-compare out4 out_empty || fail=1
+compare out4 out_skip || fail=1
 
 # -n wins (as the last option)
 touch a b || framework_failure_
 echo y | returns_ 1 mv -vifn a b 2>/dev/null > out5 || fail=1
-compare out5 out_empty || fail=1
+compare out5 out_skip || fail=1
 
 # options --backup and --no-clobber are mutually exclusive
 touch a || framework_failure_