2007-09-06 16:57:03

Create hard links in Python

#!/usr/bin/env python
#################################################################
# Who: James Conner
# When: Sep 05, 2007
# What: hard_link_sync
# Version: 0.0.2
# Why: Hard links are needed for contractors to access deep
#      hierarchy files.
#################################################################
# Updates:
# Ver:Who:When:Why
# 0.0.1:James Conner:Sep 05 2007:Initial creation
# 0.0.2:James Conner:Sep 06 2007:Check using os.samefile
#################################################################
import os,sys
from optparse import OptionParser

#################################################################
# Global Variables
#################################################################
#----------------------------------------------------------------
# The CONTRACTOR_DIR gets created under the mount point.  This is
# where all hard links will be created.
#----------------------------------------------------------------
CONTRACTOR_DIR="/contractor"
sys.path.append('/usr/local/bin')

#################################################################
# Option Parser
#################################################################
parser = OptionParser(version = "0.0.2")

parser.add_option('-d','--directory',
  dest='dir_info',
  default='',
  metavar='DIRNAME',
  help=('Perform the action on a directory and its recursive path'))

parser.add_option('-o','--output',
  dest='stdout_info',
  default='',
  metavar='FILENAME',
  help=('Output to a file instead of stdout'))
(opts, arg) = parser.parse_args()

#################################################################
# Functions
#################################################################
#----------------------------------------------------------------
# The find_mount function takes a path as a parameter.  It looks
# at the path to find the highest mount point by splitting the
# path by the "/" character into a list, and then performing the
# "ismount" function from os.path.  Each iteration of the while
# loop looks at 1 fewer items in the path list.  If the counter
# reaches 0, that means the filesystem is "/" and thus sets the
# path to "/".
#----------------------------------------------------------------
def find_mount(path):
  while not os.path.ismount(path):
    splitpath=path.split("/")
    count=len(splitpath)-1
    path="/".join(splitpath[0:count])
    if count == 0:
      path = "/"
      break
  return path

#----------------------------------------------------------------
# The hardlink function takes 3 variables to make it happen. The
# absolute path to the file to be linked to, the highest mount
# point of the filesystem, and the filename (not absolute).
#----------------------------------------------------------------
def hardlink(absolute,mounted_fs,filename):
  if os.path.exists(mounted_fs+CONTRACTOR_DIR):
    splitpath_abs=absolute.split("/")
    if mounted_fs != "/":
      splitpath_mnt=mounted_fs.split("/")
    else:
      splitpath_mnt=mounted_fs
    splitpath_file=filename.split("/")
    abs_len=len(splitpath_abs)
    mnt_len=len(splitpath_mnt)
    path_without_mounted="/".join(splitpath_abs[mnt_len:-1])
    file_to_link=mounted_fs+CONTRACTOR_DIR+"/"+path_without_mounted+"/"+splitpath_file[-1]
    path_to_make=mounted_fs+CONTRACTOR_DIR+"/"+path_without_mounted
    if not os.path.exists(path_to_make):
      os.makedirs(path_to_make, 0775)
      print path_to_make, "created!"
    if not os.path.isfile(file_to_link):
      os.link(absolute,file_to_link)
      print file_to_link,"created!"
    else:
      if os.path.samefile(absolute, file_to_link):
        print file_to_link, "already exists!"
      else:
        print "ERROR:",absolute,"is not the same file as",file_to_link+"!"
        os.remove(file_to_link)
        print file_to_link,"has been removed!"
        os.link(absolute,file_to_link)
        print file_to_link, "successfully relinked!"
  else:
    if os.path.isfile(mounted_fs+CONTRACTOR_DIR):
      print mounted_fs+CONTRACTOR_DIR,"is a file, not a directory!"
      sys.exit(12)
    else:
      os.makedirs(mounted_fs+CONTRACTOR_DIR, 0775)
      print mounted_fs+CONTRACTOR_DIR,"created!"
      hardlink(absolute,mounted_fs,filename)

#----------------------------------------------------------------
# The traverse_dir function takes a target directory, and the
# highest mounted path.  It lists the contents of a directory,
# and passes off files to the hardlink function, while other dirs
# are called recursively until all sub-trees are exhausted.
#----------------------------------------------------------------
def traverse_dir(parent_dir,mount_path):
  if os.path.isdir(parent_dir):
    for i in os.listdir(parent_dir):
      listed_target=os.path.abspath(parent_dir)+"/"+i
      if os.path.isfile(listed_target):
        just_the_filename=listed_target.split("/")[-1]
        hardlink(listed_target,mount_path,just_the_filename)
      if os.path.isdir(listed_target):
        traverse_dir(listed_target,mount_path)

#################################################################
# Program Execution
#################################################################
#----------------------------------------------------------------
# Here's where the fun starts.
# if the -o or --output option has been declared, then we
# redirect stdout to a file, taking care to preserve the old
# stdout, just in case we really need it.
#----------------------------------------------------------------
if opts.stdout_info:
  old_stdout = sys.stdout
  out_file = open(opts.stdout_info, 'w')
  sys.stdout = out_file

#----------------------------------------------------------------
# Happy Happy Joy Joy
#----------------------------------------------------------------
if len(sys.argv) < 2:
  print "No arguments supplied."
  print "Please type",sys.argv[0],"-h to see the options for this program."
elif opts.dir_info:
  if os.path.isdir(opts.dir_info):
    mount_path=find_mount(os.path.abspath(opts.dir_info))
    traverse_dir(os.path.abspath(opts.dir_info),mount_path)
  else:
    print "Not a directory!"
    sys.exit(10)
elif arg:
  for i in arg:
    if os.path.isfile(i):
      mount_path=find_mount(os.path.abspath(i))
      hardlink(os.path.abspath(i),mount_path,i)
    else:
      print "Not a file!"
      sys.exit(11)
else:
  sys.exit(99)

Tags:   python, linux     |    Perm Link:   Create hard links in Python



James Conner