mirror of https://github.com/01-edu/public.git
Xavier Petit
4 years ago
1 changed files with 23 additions and 70 deletions
@ -1,87 +1,40 @@ |
|||||||
package main |
package main |
||||||
|
|
||||||
import ( |
import ( |
||||||
|
"flag" |
||||||
"fmt" |
"fmt" |
||||||
"os" |
"os" |
||||||
"strconv" |
|
||||||
) |
) |
||||||
|
|
||||||
func numberOfBytes(args []string) (int, []string) { |
func check(err error) { |
||||||
n := len(args) |
|
||||||
nbytes := 0 |
|
||||||
var files []string |
|
||||||
for i, v := range args { |
|
||||||
var err error |
|
||||||
_, err = strconv.Atoi(v) |
|
||||||
if v == "-c" { |
|
||||||
if i >= n-1 { |
|
||||||
fmt.Printf("tail: option requires an argument -- 'c'\nTry 'tail --help' for more information.") |
|
||||||
os.Exit(1) |
|
||||||
} |
|
||||||
arg := args[i+1] |
|
||||||
|
|
||||||
nbytes, err = strconv.Atoi(arg) |
|
||||||
|
|
||||||
if err != nil { |
|
||||||
fmt.Printf("tail: invalid number of bytes: `%s`\n", arg) |
|
||||||
os.Exit(1) |
|
||||||
} |
|
||||||
continue |
|
||||||
} |
|
||||||
|
|
||||||
if err != nil { |
|
||||||
files = append(files, v) |
|
||||||
} |
|
||||||
} |
|
||||||
return nbytes, files |
|
||||||
} |
|
||||||
|
|
||||||
func fileSize(fi *os.File) int64 { |
|
||||||
fil, err := fi.Stat() |
|
||||||
|
|
||||||
if err != nil { |
if err != nil { |
||||||
fmt.Println(err) |
panic(err) |
||||||
return 0 |
|
||||||
} |
} |
||||||
|
|
||||||
return fil.Size() |
|
||||||
} |
} |
||||||
|
|
||||||
func main() { |
func main() { |
||||||
n := len(os.Args) |
var bytes int64 |
||||||
if n < 4 { |
flag.Int64Var(&bytes, "c", 0, "output the last NUM bytes") |
||||||
fmt.Println("Not enough arguments") |
flag.Parse() |
||||||
os.Exit(1) |
filenames := flag.Args() |
||||||
} |
for i, filename := range filenames { |
||||||
|
file, err := os.Open(filename) |
||||||
nbytes, files := numberOfBytes(os.Args[1:]) |
check(err) |
||||||
|
defer file.Close() |
||||||
printName := len(files) > 1 |
fileInfo, err := file.Stat() |
||||||
|
check(err) |
||||||
// open files for reading only
|
offset := fileInfo.Size() - bytes |
||||||
for j, f := range files { |
if offset < 0 { |
||||||
fi, err := os.Open(f) |
offset = 0 |
||||||
if err != nil { |
|
||||||
fmt.Printf("tail: cannot open '%s' for reading: No such file or directory\n", f) |
|
||||||
os.Exit(1) |
|
||||||
} |
} |
||||||
if printName { |
b := make([]byte, fileInfo.Size()-offset) |
||||||
fmt.Printf("==> %s <==\n", f) |
_, err = file.ReadAt(b, offset) |
||||||
|
check(err) |
||||||
|
if len(filenames) > 1 { |
||||||
|
fmt.Println("==>", filename, "<==") |
||||||
} |
} |
||||||
read := make([]byte, int(nbytes)) |
os.Stdout.Write(b) |
||||||
_, er := fi.ReadAt(read, fileSize(fi)-int64(nbytes)) |
if i < len(filenames)-1 { |
||||||
if er != nil { |
|
||||||
fmt.Println(er.Error()) |
|
||||||
} |
|
||||||
|
|
||||||
for _, c := range read { |
|
||||||
fmt.Printf("%c", rune(c)) |
|
||||||
} |
|
||||||
|
|
||||||
if j < len(files)-1 { |
|
||||||
fmt.Println() |
fmt.Println() |
||||||
} |
} |
||||||
|
|
||||||
fi.Close() |
|
||||||
} |
} |
||||||
} |
} |
||||||
|
Loading…
Reference in new issue