190f5ba538bf40bcf4fd41049c7bf4296d3ffc9c7Benjamin Peterson#! /usr/bin/env python3
2ec758ead391daa2ce0e5697aa0e67ec3ba0f37afGuido van Rossum
3ec758ead391daa2ce0e5697aa0e67ec3ba0f37afGuido van Rossum# findlinksto
4ec758ead391daa2ce0e5697aa0e67ec3ba0f37afGuido van Rossum#
55ec8b525d26aad1bc77ef81aefb081250478cd37Guido van Rossum# find symbolic links to a path matching a regular expression
6ec758ead391daa2ce0e5697aa0e67ec3ba0f37afGuido van Rossum
75ec8b525d26aad1bc77ef81aefb081250478cd37Guido van Rossumimport os
85ec8b525d26aad1bc77ef81aefb081250478cd37Guido van Rossumimport sys
9d683504b85206334aba32e8706ca6cb15b3efbf7Andrew M. Kuchlingimport re
105ec8b525d26aad1bc77ef81aefb081250478cd37Guido van Rossumimport getopt
11ec758ead391daa2ce0e5697aa0e67ec3ba0f37afGuido van Rossum
125ec8b525d26aad1bc77ef81aefb081250478cd37Guido van Rossumdef main():
1370c4378dbcfdcbeef6fb3aa348f32ed862fe8eb7Tim Peters    try:
1470c4378dbcfdcbeef6fb3aa348f32ed862fe8eb7Tim Peters        opts, args = getopt.getopt(sys.argv[1:], '')
1570c4378dbcfdcbeef6fb3aa348f32ed862fe8eb7Tim Peters        if len(args) < 2:
16d683504b85206334aba32e8706ca6cb15b3efbf7Andrew M. Kuchling            raise getopt.GetoptError('not enough arguments', None)
17b940e113bf90ff71b0ef57414ea2beea9d2a4bc0Guido van Rossum    except getopt.GetoptError as msg:
1870c4378dbcfdcbeef6fb3aa348f32ed862fe8eb7Tim Peters        sys.stdout = sys.stderr
196afaeb757af0dbd8508a0f2352ade61e41bec84cCollin Winter        print(msg)
206afaeb757af0dbd8508a0f2352ade61e41bec84cCollin Winter        print('usage: findlinksto pattern directory ...')
2170c4378dbcfdcbeef6fb3aa348f32ed862fe8eb7Tim Peters        sys.exit(2)
2270c4378dbcfdcbeef6fb3aa348f32ed862fe8eb7Tim Peters    pat, dirs = args[0], args[1:]
23d683504b85206334aba32e8706ca6cb15b3efbf7Andrew M. Kuchling    prog = re.compile(pat)
2470c4378dbcfdcbeef6fb3aa348f32ed862fe8eb7Tim Peters    for dirname in dirs:
254e6531e7dee5ff9b27c108e8614d336657e68a21Alexandre Vassalotti        os.walk(dirname, visit, prog)
265ec8b525d26aad1bc77ef81aefb081250478cd37Guido van Rossum
275ec8b525d26aad1bc77ef81aefb081250478cd37Guido van Rossumdef visit(prog, dirname, names):
2870c4378dbcfdcbeef6fb3aa348f32ed862fe8eb7Tim Peters    if os.path.islink(dirname):
2970c4378dbcfdcbeef6fb3aa348f32ed862fe8eb7Tim Peters        names[:] = []
3070c4378dbcfdcbeef6fb3aa348f32ed862fe8eb7Tim Peters        return
3170c4378dbcfdcbeef6fb3aa348f32ed862fe8eb7Tim Peters    if os.path.ismount(dirname):
326afaeb757af0dbd8508a0f2352ade61e41bec84cCollin Winter        print('descend into', dirname)
3370c4378dbcfdcbeef6fb3aa348f32ed862fe8eb7Tim Peters    for name in names:
3470c4378dbcfdcbeef6fb3aa348f32ed862fe8eb7Tim Peters        name = os.path.join(dirname, name)
3570c4378dbcfdcbeef6fb3aa348f32ed862fe8eb7Tim Peters        try:
3670c4378dbcfdcbeef6fb3aa348f32ed862fe8eb7Tim Peters            linkto = os.readlink(name)
37d683504b85206334aba32e8706ca6cb15b3efbf7Andrew M. Kuchling            if prog.search(linkto) is not None:
386afaeb757af0dbd8508a0f2352ade61e41bec84cCollin Winter                print(name, '->', linkto)
398b33dd8e547790af86e9fc85ea6c315ead276b6eAndrew Svetlov        except OSError:
4070c4378dbcfdcbeef6fb3aa348f32ed862fe8eb7Tim Peters            pass
41ec758ead391daa2ce0e5697aa0e67ec3ba0f37afGuido van Rossum
42e236b38731823aeb87bb6d101062f54a72044954Andrew M. Kuchlingif __name__ == '__main__':
43e236b38731823aeb87bb6d101062f54a72044954Andrew M. Kuchling    main()
44