Skip to content

Instantly share code, notes, and snippets.

@KaoruNishikawa
Last active August 11, 2022 03:54
Show Gist options
  • Save KaoruNishikawa/8f1f7f9c9f8c22b033b907126afe94fb to your computer and use it in GitHub Desktop.
Save KaoruNishikawa/8f1f7f9c9f8c22b033b907126afe94fb to your computer and use it in GitHub Desktop.
Collect directories in one place
#!/usr/bin/env python3
import shutil
import subprocess
import sys
import time
from pathlib import Path
save_dir = Path.home() / "Downloads" / "to_upload"
def get_all_git_repositories():
cmd = ["find", "/", "-name", ".git"]
res = subprocess.run(cmd, capture_output=True)
repos = res.stdout.decode("utf-8").split("\n")
return [Path(p).parent for p in repos if p]
def sanitize_path(path):
return str(path).replace("/", "..").strip(".")
def get_size(path):
cmd = ["du", "-ms", str(path)] # unit: MB
res = subprocess.run(cmd, capture_output=True)
size, _ = res.stdout.decode("utf-8").split(maxsplit=1)
return int(size) * 1e6
def ask(msg, target):
print(msg, ":", target)
while True:
ans = input("Continue? [y/n] : ")
if ans.lower().startswith("y"):
break
if ans.lower().startswith("n"):
print(f"Skipping {target}")
return False
print("Please choose either of [y/n]")
return True
def write(path):
if not save_dir.exists():
save_dir.mkdir()
out_path = save_dir / sanitize_path(path)
if path.is_file():
if out_path.exists():
print("Output already exists, skipping")
return
shutil.copyfile(path, out_path)
return
if (out_path.parent / (out_path.name + ".tar.gz")).exists():
print("Output already exists, skipping")
return
size = get_size(path)
if size > 100e6:
if not ask(f"Large package (size={size / 1e6}MB)", path):
return
shutil.make_archive(out_path, "gztar", path)
def get_dotfiles():
_candidates = [".bashrc", ".bash_profile", ".zshrc", ".zprofile", ".profile"]
ret = []
for filename in _candidates:
path = Path.home() / filename
if path.exists():
ret.append(path)
return ret
def get_all_python_file():
out_dir = save_dir / ".." / "_pyfiles"
if not out_dir.exists():
out_dir.mkdir()
cmd = ["find", "/", "-name", '"*.py"']
res = subprocess.run(cmd, capture_output=True)
repos = res.stdout.decode("utf-8").split("\n")
files = [Path(p).parent for p in repos if p]
_ = [shutil.copyfile(p, out_dir / sanitize_path(p)) for p in files]
return out_dir
if __name__ == "__main__":
import argparse
p = argparse.ArgumentParser()
p.add_argument("--git", action="store_true")
p.add_argument("--here", action="store_true")
p.add_argument("--add", type=str, nargs="*")
p.add_argument("--dots", action="store_true")
p.add_argument("--py", action="store_true")
args = p.parse_args()
if sum(map(lambda x: bool(x), [args.git, args.here, args.add, args.dots, args.py])) > 1:
sys.exit(print("Conflicting options specified"))
paths = []
if args.git:
paths = get_all_git_repositories()
elif args.add:
paths = [Path(p) for p in args.add]
elif args.dots:
paths = get_dotfiles()
elif args.py:
paths = [get_all_python_file()]
elif args.here:
paths = [Path(".")]
paths = list(map(lambda p: p.resolve(), paths))
for path in paths.copy():
try:
save_dir.relative_to(path)
print("Output path recursively included, skipping : ", path)
paths.remove(path)
except ValueError:
pass
if paths:
if not ask("About to process", paths):
sys.exit("Quit")
for path in paths:
print("Processing", path)
write(path)
print(f"All {len(paths)} files completed")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment