parent
							
								
									b938c60bcf
								
							
						
					
					
						commit
						504dd8ac24
					
				
				 1 changed files with 74 additions and 0 deletions
			
			
		@ -0,0 +1,74 @@ | 
				
			|||||||
 | 
					#!/usr/bin/python | 
				
			||||||
 | 
					# (c) 2015 Taeyeon Mori | 
				
			||||||
 | 
					# A simple script to make ln -s less painful | 
				
			||||||
 | 
					# | 
				
			||||||
 | 
					# Because of how symbolic links work (they're just a pathname that the OS reads and follows), | 
				
			||||||
 | 
					# the link target path must always be relative to the symlink's containing directory, OR | 
				
			||||||
 | 
					# an absolute path altogether. Unfortunately, ln -s does not automatically solve this issue | 
				
			||||||
 | 
					# which makes it painful to create a relative symlink somewhere outside the current working | 
				
			||||||
 | 
					# directory (It screws up shell completion for instance) | 
				
			||||||
 | 
					# This script performs the path transformation before creating the link and can therefore be | 
				
			||||||
 | 
					# used without worries of creating broken symlinks because one forgot to apply the correct | 
				
			||||||
 | 
					# relative adjustment to the target path | 
				
			||||||
 | 
					# | 
				
			||||||
 | 
					# ex: | 
				
			||||||
 | 
					# $ lns -v some-file dir/some-link | 
				
			||||||
 | 
					# ln -s '../some-file' 'dir/some-link' | 
				
			||||||
 | 
					# $ lns -v file ../derp/link # inside a directory called 'herp' | 
				
			||||||
 | 
					# ln -s '../herp/file' '../derp/link' | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import os | 
				
			||||||
 | 
					import argparse | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def transport_relpath(path, old_anchor, new_anchor): | 
				
			||||||
 | 
					    """ | 
				
			||||||
 | 
					    :brief: Transport a relative path from one anchor to another | 
				
			||||||
 | 
					    Anchors must both be absolute paths, path must be relative (to old_anchor) | 
				
			||||||
 | 
					    """ | 
				
			||||||
 | 
					    return os.path.relpath(os.path.normpath(os.path.join(old_anchor, path)), new_anchor) | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def verbose_symlink(target, dest): | 
				
			||||||
 | 
					    print("ln -s '%s' '%s'" % (target, dest)) | 
				
			||||||
 | 
					    return os.symlink(target, dest) | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def main(argv): | 
				
			||||||
 | 
					    # Command line interface to make_symlink() | 
				
			||||||
 | 
					    parser = argparse.ArgumentParser(prog=argv[0], | 
				
			||||||
 | 
					                                     description="A 'ln -s' command that automatically translates relative target paths to be relative to the resulting symlink's containing directory when necessary.") | 
				
			||||||
 | 
					    parser.add_argument("target", help="The file(s) to create symlink(s) to", nargs="+") | 
				
			||||||
 | 
					    parser.add_argument("destination", help="The path of the symbolic link(s) to create") | 
				
			||||||
 | 
					    parser.add_argument("-v", "--verbose", help="Print every operation", | 
				
			||||||
 | 
					                        dest="symlink", const=verbose_symlink, action="store_const", default=os.symlink) | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    args = parser.parse_args(argv[1:]) | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # Multiple | 
				
			||||||
 | 
					    if len(args.target) > 1: | 
				
			||||||
 | 
					        if not os.path.isdir(args.destination): | 
				
			||||||
 | 
					            print("Destination must be an existing directory when multiple targets are passed!") | 
				
			||||||
 | 
					        for target in args.target: | 
				
			||||||
 | 
					            dest = os.path.join(args.destination, os.path.basename(target)) | 
				
			||||||
 | 
					            args.symlink(target if os.path.isabs(target) else transport_relpath(target, os.curdir, args.destination), dest) | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # One | 
				
			||||||
 | 
					    else: | 
				
			||||||
 | 
					        target = args.target[0] | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        dest = ldir = args.destination | 
				
			||||||
 | 
					        if os.path.isdir(dest): | 
				
			||||||
 | 
					            dest = os.path.join(dest, os.path.basename(target)) | 
				
			||||||
 | 
					        else: | 
				
			||||||
 | 
					            ldir = os.path.dirname(dest) | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        args.symlink(target if os.path.isabs(target) else transport_relpath(target, os.curdir, ldir), dest) | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return 0 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if __name__ == "__main__": | 
				
			||||||
 | 
					    import sys | 
				
			||||||
 | 
					    sys.exit(main(sys.argv)) | 
				
			||||||
					Loading…
					
					
				
		Reference in new issue