gopkg.in/hugelgupf/u-root.v9@v9.0.0-20180831063832-3f6f1057f09b/cmds/ls/ls.go (about)

     1  // Copyright 2013-2017 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  // Ls prints the contents of a directory.
     6  //
     7  // Synopsis:
     8  //     ls [OPTIONS] [DIRS]...
     9  //
    10  // Options:
    11  //     -l: long form
    12  //     -Q: quoted
    13  //     -R: equivalent to findutil's find
    14  //
    15  // Bugs:
    16  //     With the `-R` flag, directories are only ever printed once.
    17  package main
    18  
    19  import (
    20  	"fmt"
    21  	"io"
    22  	"log"
    23  	"os"
    24  	"path/filepath"
    25  	"text/tabwriter"
    26  
    27  	flag "github.com/spf13/pflag"
    28  )
    29  
    30  var (
    31  	all     = flag.BoolP("all", "a", false, "show hidden files")
    32  	human   = flag.BoolP("human-readable", "h", false, "human readable sizes")
    33  	long    = flag.BoolP("long", "l", false, "long form")
    34  	quoted  = flag.BoolP("quote-name", "Q", false, "quoted")
    35  	recurse = flag.BoolP("recursive", "R", false, "equivalent to findutil's find")
    36  )
    37  
    38  func stringer(fi fileInfo) fmt.Stringer {
    39  	var s fmt.Stringer = fi
    40  	if *quoted {
    41  		s = quotedStringer{fileInfo: fi}
    42  	}
    43  	if *long {
    44  		s = longStringer{
    45  			fileInfo: fi,
    46  			comp:     s,
    47  			human:    *human,
    48  		}
    49  	}
    50  	return s
    51  }
    52  
    53  func listName(d string, w io.Writer, prefix bool) error {
    54  	return filepath.Walk(d, func(path string, osfi os.FileInfo, err error) error {
    55  		// Soft error. Useful when a permissions are insufficient to
    56  		// stat one of the files.
    57  		if err != nil {
    58  			log.Printf("%s: %v\n", path, err)
    59  			return nil
    60  		}
    61  
    62  		fi := extractImportantParts(path, osfi)
    63  
    64  		if *recurse {
    65  			// Mimic find command
    66  			fi.name = path
    67  		} else if path == d {
    68  			// Starting directory is a dot when non-recursive
    69  			if osfi.IsDir() {
    70  				fi.name = "."
    71  				if prefix {
    72  					fmt.Printf("%q\n", d)
    73  				}
    74  			}
    75  		}
    76  
    77  		// Hide .files unless -a was given
    78  		if *all || fi.name[0] != '.' {
    79  			// Print the file in the proper format.
    80  			fmt.Fprintln(w, stringer(fi))
    81  		}
    82  
    83  		// Skip directories when non-recursive.
    84  		if path != d && fi.mode.IsDir() && !*recurse {
    85  			return filepath.SkipDir
    86  		}
    87  		return nil
    88  	})
    89  }
    90  
    91  func main() {
    92  	flag.Parse()
    93  
    94  	// Write output in tabular form.
    95  	w := new(tabwriter.Writer)
    96  	w.Init(os.Stdout, 0, 0, 1, ' ', 0)
    97  	defer w.Flush()
    98  
    99  	// Array of names to list.
   100  	names := flag.Args()
   101  	if len(names) == 0 {
   102  		names = []string{"."}
   103  	}
   104  
   105  	// Is a name a directory? If so, list it in its own section.
   106  	prefix := len(names) > 1
   107  	for _, d := range names {
   108  		if err := listName(d, w, prefix); err != nil {
   109  			log.Printf("error while listing %#v: %v", d, err)
   110  		}
   111  		w.Flush()
   112  	}
   113  }