commit: c7250c2e64a8bccab55915514887d9a7ccc0ee5b
parent b8e206e0122b76df02aa9fc980d160361b66ab35
Author: Haelwenn (lanodan) Monnier <contact@hacktivis.me>
Date: Sun, 28 Dec 2025 09:24:42 +0100
cmd/mv: add -I option
Diffstat:
| M | cmd/mv.1 | 39 | ++++++++++++++++++++------------------- |
| M | cmd/mv.c | 25 | ++++++++++++++++++++----- |
2 files changed, 40 insertions(+), 24 deletions(-)
diff --git a/cmd/mv.1 b/cmd/mv.1
@@ -1,7 +1,7 @@
.\" utils-std: Collection of commonly available Unix tools
.\" Copyright 2017 Haelwenn (lanodan) Monnier <contact+utils@hacktivis.me>
.\" SPDX-License-Identifier: MPL-2.0
-.Dd November 10, 2024
+.Dd December 28, 2025
.Dt MV 1
.Os
.Sh NAME
@@ -9,17 +9,17 @@
.Nd move and rename files
.Sh SYNOPSIS
.Nm
-.Op Fl f Ns | Ns Fl i Ns | Ns Fl n
+.Op Fl f Ns | Ns Fl Ii Ns | Ns Fl n
.Op Fl Tv
.Ar source
.Ar destfile
.Nm
-.Op Fl f Ns | Ns Fl i Ns | Ns Fl n
+.Op Fl f Ns | Ns Fl Ii Ns | Ns Fl n
.Op Fl v
.Ar source...
.Ar destdir
.Nm
-.Op Fl f Ns | Ns Fl i Ns | Ns Fl n
+.Op Fl f Ns | Ns Fl Ii Ns | Ns Fl n
.Op Fl v
.Fl t Ar destdir
.Ar source...
@@ -52,27 +52,16 @@ to create the full destination path.
.Bl -tag -width _f
.It Fl f
Force, do not ask before overwriting to the destination path.
-Overrides previously set
-.Fl i
-and
-.Fl n
-options.
+.It Fl I
+Prompt for confirmation before moving a file,
+implies
+.Fl i .
.It Fl i
Interactive, causes
.Nm
to ask before overwriting a file.
-Overrides previously set
-.Fl f
-and
-.Fl n
-options.
.It Fl n
No-clobber, never overwrite.
-Overrides previously set
-.Fl f
-and
-.Fl i
-options.
.It Fl t Ar destdir
Set the destination directory.
.It Fl T
@@ -80,6 +69,14 @@ Always treat destination as a file.
.It Fl v
Verbose, write which action has been done.
.El
+.Pp
+For the
+.Fl f ,
+.Fl Ii ,
+and
+.Fl n
+options, the last one specified determines the behavior of
+.Nm .
.Sh EXIT STATUS
.Ex -std
.Sh STANDARDS
@@ -89,6 +86,10 @@ IEEE Std 1003.1-2024 (“POSIX.1”)
specification.
.Pp
The
+.Fl I
+option is an utils-std original extension.
+.br
+The
.Fl n ,
.Fl t Ar destdir ,
.Fl T ,
diff --git a/cmd/mv.c b/cmd/mv.c
@@ -43,6 +43,7 @@
const char *argv0 = "mv";
bool no_clob = false, force = false, interact = false, verbose = false;
+bool always_interact = false;
bool opt_T = false;
static int stdin_tty = 0;
@@ -265,6 +266,17 @@ do_renameat(struct named_fd srcdir,
}
}
}
+ else if(interact && always_interact)
+ {
+ if(!consentf("mv: Move file '%s%s%s' to '%s%s%s'? [yN] ",
+ srcdir.name,
+ srcdir.sep,
+ src,
+ destdir.name,
+ destdir.sep,
+ dest))
+ return 0;
+ }
if(renameat(srcdir.fd, src, destdir.fd, dest) < 0)
{
@@ -408,9 +420,9 @@ do_renameat(struct named_fd srcdir,
static void
usage(void)
{
- fprintf(stderr, "Usage: mv [-f|-i|-n] [-Tv] source dest\n");
- fprintf(stderr, " mv [-f|-i|-n] [-v] source... destdir\n");
- fprintf(stderr, " mv [-f|-i|-n] [-v] -t destdir source...\n");
+ fprintf(stderr, "Usage: mv [-f|-Ii|-n] [-Tv] source dest\n");
+ fprintf(stderr, " mv [-f|-Ii|-n] [-v] source... destdir\n");
+ fprintf(stderr, " mv [-f|-Ii|-n] [-v] -t destdir source...\n");
}
int
@@ -432,6 +444,7 @@ main(int argc, char *argv[])
// clang-format off
static struct option opts[] = {
{"force", no_argument, NULL, 'f'},
+ {"always-interactive", no_argument, NULL, 'I'},
{"interactive", no_argument, NULL, 'i'},
{"no-clobber", no_argument, NULL, 'n'},
{"target-directory", required_argument, NULL, 't'},
@@ -442,9 +455,9 @@ main(int argc, char *argv[])
// clang-format on
// Need + as first character to get POSIX-style option parsing
- for(int c = -1; (c = getopt_long(argc, argv, "+:fint:Tv", opts, NULL)) != -1;)
+ for(int c = -1; (c = getopt_long(argc, argv, "+:fIint:Tv", opts, NULL)) != -1;)
#else
- for(int c = -1; (c = getopt_nolong(argc, argv, ":fint:Tv")) != -1;)
+ for(int c = -1; (c = getopt_nolong(argc, argv, ":fIint:Tv")) != -1;)
#endif
{
switch(c)
@@ -454,7 +467,9 @@ main(int argc, char *argv[])
interact = false;
no_clob = false;
break;
+ case 'I':
case 'i':
+ if(c == 'I') always_interact = true;
force = false;
interact = true;
no_clob = false;