github.com/pkg/sftp@v1.13.6/example_test.go (about) 1 package sftp_test 2 3 import ( 4 "bufio" 5 "fmt" 6 "io" 7 "log" 8 "os" 9 "os/exec" 10 "path" 11 "strings" 12 13 "github.com/pkg/sftp" 14 "golang.org/x/crypto/ssh" 15 ) 16 17 func Example() { 18 var conn *ssh.Client 19 20 // open an SFTP session over an existing ssh connection. 21 client, err := sftp.NewClient(conn) 22 if err != nil { 23 log.Fatal(err) 24 } 25 defer client.Close() 26 27 // walk a directory 28 w := client.Walk("/home/user") 29 for w.Step() { 30 if w.Err() != nil { 31 continue 32 } 33 log.Println(w.Path()) 34 } 35 36 // leave your mark 37 f, err := client.Create("hello.txt") 38 if err != nil { 39 log.Fatal(err) 40 } 41 if _, err := f.Write([]byte("Hello world!")); err != nil { 42 log.Fatal(err) 43 } 44 f.Close() 45 46 // check it's there 47 fi, err := client.Lstat("hello.txt") 48 if err != nil { 49 log.Fatal(err) 50 } 51 log.Println(fi) 52 } 53 54 func ExampleNewClientPipe() { 55 // Connect to a remote host and request the sftp subsystem via the 'ssh' 56 // command. This assumes that passwordless login is correctly configured. 57 cmd := exec.Command("ssh", "example.com", "-s", "sftp") 58 59 // send errors from ssh to stderr 60 cmd.Stderr = os.Stderr 61 62 // get stdin and stdout 63 wr, err := cmd.StdinPipe() 64 if err != nil { 65 log.Fatal(err) 66 } 67 rd, err := cmd.StdoutPipe() 68 if err != nil { 69 log.Fatal(err) 70 } 71 72 // start the process 73 if err := cmd.Start(); err != nil { 74 log.Fatal(err) 75 } 76 defer cmd.Wait() 77 78 // open the SFTP session 79 client, err := sftp.NewClientPipe(rd, wr) 80 if err != nil { 81 log.Fatal(err) 82 } 83 84 // read a directory 85 list, err := client.ReadDir("/") 86 if err != nil { 87 log.Fatal(err) 88 } 89 90 // print contents 91 for _, item := range list { 92 fmt.Println(item.Name()) 93 } 94 95 // close the connection 96 client.Close() 97 } 98 99 func ExampleClient_Mkdir_parents() { 100 // Example of mimicing 'mkdir --parents'; I.E. recursively create 101 // directoryies and don't error if any directories already exists. 102 var conn *ssh.Client 103 104 client, err := sftp.NewClient(conn) 105 if err != nil { 106 log.Fatal(err) 107 } 108 defer client.Close() 109 110 sshFxFailure := uint32(4) 111 mkdirParents := func(client *sftp.Client, dir string) (err error) { 112 var parents string 113 114 if path.IsAbs(dir) { 115 // Otherwise, an absolute path given below would be turned in to a relative one 116 // by splitting on "/" 117 parents = "/" 118 } 119 120 for _, name := range strings.Split(dir, "/") { 121 if name == "" { 122 // Paths with double-/ in them should just move along 123 // this will also catch the case of the first character being a "/", i.e. an absolute path 124 continue 125 } 126 parents = path.Join(parents, name) 127 err = client.Mkdir(parents) 128 if status, ok := err.(*sftp.StatusError); ok { 129 if status.Code == sshFxFailure { 130 var fi os.FileInfo 131 fi, err = client.Stat(parents) 132 if err == nil { 133 if !fi.IsDir() { 134 return fmt.Errorf("file exists: %s", parents) 135 } 136 } 137 } 138 } 139 if err != nil { 140 break 141 } 142 } 143 return err 144 } 145 146 err = mkdirParents(client, "/tmp/foo/bar") 147 if err != nil { 148 log.Fatal(err) 149 } 150 } 151 152 func ExampleFile_ReadFrom_bufio() { 153 // Using Bufio to buffer writes going to an sftp.File won't buffer as it 154 // skips buffering if the underlying writer support ReadFrom. The 155 // workaround is to wrap your writer in a struct that only implements 156 // io.Writer. 157 // 158 // For background see github.com/pkg/sftp/issues/125 159 160 var data_source io.Reader 161 var f *sftp.File 162 type writerOnly struct{ io.Writer } 163 bw := bufio.NewWriter(writerOnly{f}) // no ReadFrom() 164 bw.ReadFrom(data_source) 165 }