github.com/hugelgupf/u-root@v0.0.0-20191023214958-4807c632154c/cmds/core/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  	"github.com/u-root/u-root/pkg/ls"
    29  )
    30  
    31  var (
    32  	all     = flag.BoolP("all", "a", false, "show hidden files")
    33  	human   = flag.BoolP("human-readable", "h", false, "human readable sizes")
    34  	long    = flag.BoolP("long", "l", false, "long form")
    35  	quoted  = flag.BoolP("quote-name", "Q", false, "quoted")
    36  	recurse = flag.BoolP("recursive", "R", false, "equivalent to findutil's find")
    37  )
    38  
    39  func listName(stringer ls.Stringer, d string, w io.Writer, prefix bool) error {
    40  	return filepath.Walk(d, func(path string, osfi os.FileInfo, err error) error {
    41  		// Soft error. Useful when a permissions are insufficient to
    42  		// stat one of the files.
    43  		if err != nil {
    44  			log.Printf("%s: %v\n", path, err)
    45  			return nil
    46  		}
    47  
    48  		fi := ls.FromOSFileInfo(path, osfi)
    49  
    50  		if *recurse {
    51  			// Mimic find command
    52  			fi.Name = path
    53  		} else if path == d {
    54  			// Starting directory is a dot when non-recursive
    55  			if osfi.IsDir() {
    56  				fi.Name = "."
    57  				if prefix {
    58  					fmt.Printf("%q\n", d)
    59  				}
    60  			}
    61  		}
    62  
    63  		// Hide .files unless -a was given
    64  		if *all || fi.Name[0] != '.' {
    65  			// Print the file in the proper format.
    66  			fmt.Fprintln(w, stringer.FileString(fi))
    67  		}
    68  
    69  		// Skip directories when non-recursive.
    70  		if path != d && fi.Mode.IsDir() && !*recurse {
    71  			return filepath.SkipDir
    72  		}
    73  		return nil
    74  	})
    75  }
    76  
    77  func main() {
    78  	flag.Parse()
    79  
    80  	// Write output in tabular form.
    81  	w := &tabwriter.Writer{}
    82  	w.Init(os.Stdout, 0, 0, 1, ' ', 0)
    83  	defer w.Flush()
    84  
    85  	var s ls.Stringer = ls.NameStringer{}
    86  	if *quoted {
    87  		s = ls.QuotedStringer{}
    88  	}
    89  	if *long {
    90  		s = ls.LongStringer{Human: *human, Name: s}
    91  	}
    92  
    93  	// Array of names to list.
    94  	names := flag.Args()
    95  	if len(names) == 0 {
    96  		names = []string{"."}
    97  	}
    98  
    99  	// Is a name a directory? If so, list it in its own section.
   100  	prefix := len(names) > 1
   101  	for _, d := range names {
   102  		if err := listName(s, d, w, prefix); err != nil {
   103  			log.Printf("error while listing %#v: %v", d, err)
   104  		}
   105  		w.Flush()
   106  	}
   107  }