package main import ( "errors" "io" "os" "github.com/mitchellh/ioprogress" ) var ( ErrUnsupportedFile = errors.New("unsupported file") ErrThisIsDirectory = errors.New("this is directory") ErrOffsetExceedsFileSize = errors.New("offset exceeds file size") ErrNoInFile = errors.New("не указан исходный файл или он не существует") ) func Copy(fromPath string, toPath string, offset, limit int64) error { fIn, err := os.Open(fromPath) defer func() { if fIn.Close() != nil { return } }() if err != nil { return ErrNoInFile } fInInfo, err := fIn.Stat() if err != nil { return err } fInMode := fInInfo.Mode() if fInMode.IsDir() { return ErrThisIsDirectory } if !fInMode.IsRegular() { return ErrUnsupportedFile } fInSize := fInInfo.Size() switch { case offset >= fInSize: return ErrOffsetExceedsFileSize case limit == 0: limit = fInSize - offset case fInSize < limit+offset: limit = fInSize - offset default: } fOut, err := os.Create(toPath) defer func() { if fOut.Close() != nil { return } }() if err != nil { return err } pg := &ioprogress.Reader{ Reader: fIn, Size: limit, DrawFunc: ioprogress.DrawTerminalf(os.Stdout, ioprogress.DrawTextFormatBar(100)), } if _, err = fIn.Seek(offset, io.SeekStart); err != nil { return err } if _, err = io.CopyN(fOut, pg, limit); err != nil { return err } return nil }