add symlink support to recursive hardlink

This commit is contained in:
Maks Snegov 2019-01-16 23:02:35 +03:00
parent a1e4f00a3b
commit 3c15dd0373

57
main.py
View File

@ -9,35 +9,47 @@ logging.basicConfig(level=logging.DEBUG)
def hardlink_dir(src_dir, dst_dir): def hardlink_dir(src_dir, dst_dir):
"""
Make hardlink for a directory with all its content.
:param src_dir: path to source directory
:param dst_dir: path to target directory
:return: None
"""
logging.info(f'Recursive hardlinking: {src_dir} -> {dst_dir}') logging.info(f'Recursive hardlinking: {src_dir} -> {dst_dir}')
src_abs = os.path.abspath(src_dir) src_abs = os.path.abspath(src_dir)
dst_abs = os.path.abspath(dst_dir) dst_abs = os.path.abspath(dst_dir)
if os.path.isdir(dst_abs): def recursive_hardlink(src, dst):
logging.error(f"Destination directory already exists: {dst_dir}") logging.debug(f'Creating directory: {src} -> {dst}')
raise RuntimeError(f'dst dir already exists: {dst_dir}') os.mkdir(dst)
with os.scandir(src) as it:
for ent in it:
ent_dst_path = os.path.join(dst, ent.name)
if ent.is_symlink():
symlink_target = os.readlink(ent.path)
logging.debug(f"Symlink to {symlink_target}: {ent.path} -> {ent_dst_path}")
os.symlink(symlink_target, ent_dst_path)
continue
if ent.is_dir(follow_symlinks=False):
recursive_hardlink(ent.path, ent_dst_path)
continue
if ent.is_file(follow_symlinks=False):
logging.debug(f"Hardlink file: {ent.path} -> {ent_dst_path}")
os.link(ent.path, ent_dst_path)
continue
if not os.path.isdir(src_abs):
logging.error(f"Error reading source directory: {src_dir}")
raise RuntimeError(f"Error reading source directory: {src_dir}")
if os.path.exists(dst_abs):
logging.error(f"Destination already exists: {dst_dir}")
raise RuntimeError(f'Destination already exists: {dst_dir}')
recursive_hardlink(src_abs, dst_abs) recursive_hardlink(src_abs, dst_abs)
return return
def recursive_hardlink(src, dst):
logging.debug(f'Hardlink: {src} -> {dst}')
logging.debug(f'Creating top directory: {dst}')
os.mkdir(dst)
with os.scandir(src) as it:
for ent in it:
if ent.is_symlink():
logging.error(f'{ent.path}: symlink, skipping')
continue
if ent.is_dir(follow_symlinks=False):
recursive_hardlink(ent.path, os.path.join(dst, ent.name))
continue
if ent.is_file(follow_symlinks=False):
os.link(ent.path, os.path.join(dst, ent.name), follow_symlinks=False)
def main(): def main():
if len(sys.argv) != 3: if len(sys.argv) != 3:
@ -46,5 +58,6 @@ def main():
hardlink_dir(sys.argv[1], sys.argv[2]) hardlink_dir(sys.argv[1], sys.argv[2])
if __name__ == '__main__': if __name__ == '__main__':
sys.exit(main()) sys.exit(main())