github.com/rminnich/u-root@v7.0.0+incompatible/cmds/core/mv/mv.go (about)

     1  // Copyright 2012-2018 the u-root Authors. All rights reserved
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  // mv renames files and directories.
     6  //
     7  // Synopsis:
     8  //     mv SOURCE [-u] TARGET
     9  //     mv SOURCE... [-u] DIRECTORY
    10  //
    11  // Author:
    12  //     Beletti (rhiguita@gmail.com)
    13  package main
    14  
    15  import (
    16  	"flag"
    17  	"fmt"
    18  	"log"
    19  	"os"
    20  	"path/filepath"
    21  )
    22  
    23  var (
    24  	update    = flag.Bool("u", false, "move only when the SOURCE file is newer than the destination file or when the destination file is missing")
    25  	noClobber = flag.Bool("n", false, "do not overwrite an existing file")
    26  )
    27  
    28  func usage() {
    29  	fmt.Fprintf(os.Stderr, "Usage: %s [ARGS] source target\n", os.Args[0])
    30  	fmt.Fprintf(os.Stderr, "       %s [ARGS] source ... directory\n", os.Args[0])
    31  	flag.PrintDefaults()
    32  	os.Exit(1)
    33  }
    34  
    35  func moveFile(source string, dest string) error {
    36  
    37  	if *noClobber {
    38  		_, err := os.Lstat(dest)
    39  		if !os.IsNotExist(err) {
    40  			// This is either a real error if something unexpected happen during Lstat or nil
    41  			return err
    42  		}
    43  	}
    44  
    45  	if *update {
    46  		sourceInfo, err := os.Lstat(source)
    47  		if err != nil {
    48  			return err
    49  		}
    50  
    51  		destInfo, err := os.Lstat(dest)
    52  		if err != nil {
    53  			return err
    54  		}
    55  
    56  		// Check if the destination already exists and was touched later than the source
    57  		if destInfo.ModTime().After(sourceInfo.ModTime()) {
    58  			// Source is older and we don't want to "downgrade"
    59  			return nil
    60  		}
    61  	}
    62  
    63  	if err := os.Rename(source, dest); err != nil {
    64  		return err
    65  	}
    66  	return nil
    67  }
    68  
    69  func mv(files []string, todir bool) error {
    70  	if len(files) == 2 && !todir {
    71  		// Rename/move a single file
    72  		if err := moveFile(files[0], files[1]); err != nil {
    73  			return err
    74  		}
    75  	} else {
    76  		// Move one or more files into a directory
    77  		destdir := files[len(files)-1]
    78  		for _, f := range files[:len(files)-1] {
    79  			newPath := filepath.Join(destdir, filepath.Base(f))
    80  			if err := moveFile(f, newPath); err != nil {
    81  				return err
    82  			}
    83  		}
    84  	}
    85  	return nil
    86  }
    87  
    88  func main() {
    89  	var todir bool
    90  	flag.Parse()
    91  
    92  	if flag.NArg() < 2 {
    93  		usage()
    94  	}
    95  
    96  	files := flag.Args()
    97  	dest := files[len(files)-1]
    98  	if destdir, err := os.Lstat(dest); err == nil {
    99  		todir = destdir.IsDir()
   100  	}
   101  	if flag.NArg() > 2 && !todir {
   102  		fmt.Printf("Not a directory: %s\n", dest)
   103  		os.Exit(1)
   104  	}
   105  
   106  	if err := mv(files, todir); err != nil {
   107  		log.Fatalf("%v", err)
   108  	}
   109  }