Add a -h flag similar to the -h flag for ln to force mv(1) to treat a
symbolic link to a directory for the target as a symbolic link instead of a directory. This makes it possible to atomically update a symbolic link using rename(). Reviewed by: gj MFC after: 2 weeks
This commit is contained in:
parent
9e8100e77c
commit
6ce6b6c1d4
22
bin/mv/mv.1
22
bin/mv/mv.1
@ -32,7 +32,7 @@
|
||||
.\" @(#)mv.1 8.1 (Berkeley) 5/31/93
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd May 12, 2007
|
||||
.Dd August 28, 2012
|
||||
.Dt MV 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -41,7 +41,7 @@
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl f | i | n
|
||||
.Op Fl v
|
||||
.Op Fl hv
|
||||
.Ar source target
|
||||
.Nm
|
||||
.Op Fl f | i | n
|
||||
@ -81,6 +81,21 @@ option overrides any previous
|
||||
or
|
||||
.Fl n
|
||||
options.)
|
||||
.It Fl h
|
||||
If the
|
||||
.Ar target
|
||||
operand is a symbolic link to a directory,
|
||||
do not follow it.
|
||||
This causes the
|
||||
.Nm
|
||||
utility to rename the file
|
||||
.Ar source
|
||||
to the destination path
|
||||
.Ar target
|
||||
rather than moving
|
||||
.Ar source
|
||||
into the directory referenced by
|
||||
.Ar target .
|
||||
.It Fl i
|
||||
Cause
|
||||
.Nm
|
||||
@ -142,7 +157,8 @@ rm -rf source_file
|
||||
.Ex -std
|
||||
.Sh COMPATIBILITY
|
||||
The
|
||||
.Fl n
|
||||
.Fl h ,
|
||||
.Fl n ,
|
||||
and
|
||||
.Fl v
|
||||
options are non-standard and their use in scripts is not recommended.
|
||||
|
20
bin/mv/mv.c
20
bin/mv/mv.c
@ -68,7 +68,7 @@ __FBSDID("$FreeBSD$");
|
||||
/* Exit code for a failed exec. */
|
||||
#define EXEC_FAILED 127
|
||||
|
||||
static int fflg, iflg, nflg, vflg;
|
||||
static int fflg, hflg, iflg, nflg, vflg;
|
||||
|
||||
static int copy(const char *, const char *);
|
||||
static int do_move(const char *, const char *);
|
||||
@ -87,8 +87,11 @@ main(int argc, char *argv[])
|
||||
int ch;
|
||||
char path[PATH_MAX];
|
||||
|
||||
while ((ch = getopt(argc, argv, "finv")) != -1)
|
||||
while ((ch = getopt(argc, argv, "fhinv")) != -1)
|
||||
switch (ch) {
|
||||
case 'h':
|
||||
hflg = 1;
|
||||
break;
|
||||
case 'i':
|
||||
iflg = 1;
|
||||
fflg = nflg = 0;
|
||||
@ -123,6 +126,17 @@ main(int argc, char *argv[])
|
||||
exit(do_move(argv[0], argv[1]));
|
||||
}
|
||||
|
||||
/*
|
||||
* If -h was specified, treat the target as a symlink instead of
|
||||
* directory.
|
||||
*/
|
||||
if (hflg) {
|
||||
if (argc > 2)
|
||||
usage();
|
||||
if (lstat(argv[1], &sb) == 0 && S_ISLNK(sb.st_mode))
|
||||
exit(do_move(argv[0], argv[1]));
|
||||
}
|
||||
|
||||
/* It's a directory, move each file into it. */
|
||||
if (strlen(argv[argc - 1]) > sizeof(path) - 1)
|
||||
errx(1, "%s: destination pathname too long", *argv);
|
||||
@ -483,7 +497,7 @@ usage(void)
|
||||
{
|
||||
|
||||
(void)fprintf(stderr, "%s\n%s\n",
|
||||
"usage: mv [-f | -i | -n] [-v] source target",
|
||||
"usage: mv [-f | -i | -n] [-hv] source target",
|
||||
" mv [-f | -i | -n] [-v] source ... directory");
|
||||
exit(EX_USAGE);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user