diff options
author | jhb <jhb@FreeBSD.org> | 2012-08-31 14:35:01 +0000 |
---|---|---|
committer | jhb <jhb@FreeBSD.org> | 2012-08-31 14:35:01 +0000 |
commit | 55d653d5f9d103f38c4247ad282d34f3bce008dc (patch) | |
tree | a4d7515ca0e79ae9313694d57b632955e683f20c /bin | |
parent | 1829ce354683a94e219d2a4f5f6a0d8f3c0abaa6 (diff) | |
download | FreeBSD-src-55d653d5f9d103f38c4247ad282d34f3bce008dc.zip FreeBSD-src-55d653d5f9d103f38c4247ad282d34f3bce008dc.tar.gz |
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
Diffstat (limited to 'bin')
-rw-r--r-- | bin/mv/mv.1 | 22 | ||||
-rw-r--r-- | bin/mv/mv.c | 20 |
2 files changed, 36 insertions, 6 deletions
diff --git a/bin/mv/mv.1 b/bin/mv/mv.1 index 9e4d9ee..5199f27 100644 --- a/bin/mv/mv.1 +++ b/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. diff --git a/bin/mv/mv.c b/bin/mv/mv.c index e4fe007..d33b28d 100644 --- a/bin/mv/mv.c +++ b/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); } |