Last active
August 11, 2022 03:54
-
-
Save KaoruNishikawa/8f1f7f9c9f8c22b033b907126afe94fb to your computer and use it in GitHub Desktop.
Collect directories in one place
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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