Skip to content

Instantly share code, notes, and snippets.

@pcarrier
Last active December 11, 2015 18:09
Show Gist options
  • Select an option

  • Save pcarrier/4639579 to your computer and use it in GitHub Desktop.

Select an option

Save pcarrier/4639579 to your computer and use it in GitHub Desktop.
"Hardlink" a tree
package main
import (
"flag"
"log"
"os"
"path"
)
var src = flag.String("src", "/usr", "source path")
var dst = flag.String("dst", "/usr.copy", "destination path")
func copyEntries(src string, dst string) error {
f, err := os.Open(src)
if err != nil {
f.Close()
return err
}
infos, err := f.Readdir(-1)
f.Close()
if err != nil {
return err
}
errs := make(chan error, len(infos))
for _, info := range infos {
go func(info os.FileInfo) {
csrc := path.Join(src, info.Name())
cdst := path.Join(dst, info.Name())
errs <- copy(csrc, cdst, info)
}(info)
}
for i := 0; i < len(infos); i++ {
if err := <-errs; err != nil {
return err
}
}
return nil
}
func copy(src string, dst string, fi os.FileInfo) error {
mod := fi.Mode()
switch {
case mod&os.ModeSymlink != 0:
if tgt, err := os.Readlink(src); err != nil {
return err
} else {
if err := os.Symlink(tgt, dst); err != nil {
return err
}
}
case mod&os.ModeDir != 0:
if err := os.Mkdir(dst, mod); err != nil {
return err
}
if err := copyEntries(src, dst); err != nil {
return err
}
default:
if err := os.Link(src, dst); err != nil {
return err
}
}
return nil
}
func main() {
flag.Parse()
if err := os.Mkdir(*dst, 0755); err != nil && !os.IsExist(err) {
log.Fatal(err)
}
if err := copyEntries(*src, *dst); err != nil {
log.Fatal(err)
}
}
#!/usr/bin/env ruby
require 'find'
exit 1 unless ARGV.length == 2
SRC, DST = ARGV
def clone_dir srcdir, dstdir
Dir.entries(srcdir).each do |e|
next if %w[. ..].include? e
src = File.join srcdir, e
dst = File.join dstdir, e
stat = File::lstat src
case true
when stat.directory?
Dir.mkdir dst
clone_dir src, dst
when stat.file?
File.link src, dst
when stat.symlink?
File.symlink File.readlink(src), dst
end
end
end
Dir.mkdir DST
clone_dir SRC, DST
#!/usr/bin/env coffee
fs = require 'fs'
path = require 'path'
copyEntries = (src, dst) ->
fs.readdir src, (err, files) ->
for file in files
s = path.join src, file
d = path.join dst, file
copy s, d
copy = (src, dst) ->
fs.lstat src, (err, stat) ->
switch true
when stat.isFile()
fs.link src, dst, (err) ->
if err? and err.code != 'EEXIST'
console.log err.stack
when stat.isDirectory()
fs.mkdir dst, 0o0755, (err) ->
if err? and err.code != 'EEXIST'
console.log err.stack
else
copyEntries src, dst
when stat.isSymbolicLink()
fs.readlink src, (err, lsrc) ->
if err? and err.code != 'EEXIST'
console.log err.stack
else
fs.symlink lsrc, dst
else
console.log "#{src} not handled (#{stat})"
return null # tiny optimization
if require.main is module
args = process.argv[2..]
if args.length != 2
console.log "invalid usage!"
process.exit 1
else
fs.mkdir args[1], 0o0755, (err) ->
if err and err.code != 'EEXIST'
console.log err.stack
else
copy args...
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment