1#! /usr/bin/env python3
2
3# linktree
4#
5# Make a copy of a directory tree with symbolic links to all files in the
6# original tree.
7# All symbolic links go to a special symbolic link at the top, so you
8# can easily fix things if the original source tree moves.
9# See also "mkreal".
10#
11# usage: mklinks oldtree newtree
12
13import sys, os
14
15LINK = '.LINK' # Name of special symlink at the top.
16
17debug = 0
18
19def main():
20    if not 3 <= len(sys.argv) <= 4:
21        print('usage:', sys.argv[0], 'oldtree newtree [linkto]')
22        return 2
23    oldtree, newtree = sys.argv[1], sys.argv[2]
24    if len(sys.argv) > 3:
25        link = sys.argv[3]
26        link_may_fail = 1
27    else:
28        link = LINK
29        link_may_fail = 0
30    if not os.path.isdir(oldtree):
31        print(oldtree + ': not a directory')
32        return 1
33    try:
34        os.mkdir(newtree, 0o777)
35    except OSError as msg:
36        print(newtree + ': cannot mkdir:', msg)
37        return 1
38    linkname = os.path.join(newtree, link)
39    try:
40        os.symlink(os.path.join(os.pardir, oldtree), linkname)
41    except OSError as msg:
42        if not link_may_fail:
43            print(linkname + ': cannot symlink:', msg)
44            return 1
45        else:
46            print(linkname + ': warning: cannot symlink:', msg)
47    linknames(oldtree, newtree, link)
48    return 0
49
50def linknames(old, new, link):
51    if debug: print('linknames', (old, new, link))
52    try:
53        names = os.listdir(old)
54    except OSError as msg:
55        print(old + ': warning: cannot listdir:', msg)
56        return
57    for name in names:
58        if name not in (os.curdir, os.pardir):
59            oldname = os.path.join(old, name)
60            linkname = os.path.join(link, name)
61            newname = os.path.join(new, name)
62            if debug > 1: print(oldname, newname, linkname)
63            if os.path.isdir(oldname) and \
64               not os.path.islink(oldname):
65                try:
66                    os.mkdir(newname, 0o777)
67                    ok = 1
68                except:
69                    print(newname + \
70                          ': warning: cannot mkdir:', msg)
71                    ok = 0
72                if ok:
73                    linkname = os.path.join(os.pardir,
74                                            linkname)
75                    linknames(oldname, newname, linkname)
76            else:
77                os.symlink(linkname, newname)
78
79if __name__ == '__main__':
80    sys.exit(main())
81