# Backup to NEW prefix only; refuses if prefix non-empty at first run; never overwrites (same-ETag skip, else -vN). import boto3,hashlib,os B='analyticsdata123'; P='options-ml-platform/data/knowledge/popular-strategies/2026-10-27_youtube/'; L='/workspace/research/popular-strategies' s3=boto3.client('s3',region_name='ap-south-2') print('existing objects under prefix before upload:',s3.list_objects_v2(Bucket=B,Prefix=P,MaxKeys=5).get('KeyCount',0)) files=['index.html', 'PREREG.md', 'PROGRESS.md', 'scripts/gen_page.py', 'scripts/backup_s3_youtube.py', 'scripts/s12_yt_discretion.py', 'scripts/s13_yt_disc_model.py', 'scripts/yt_analyze.py', 'scripts/yt_bars.py', 'scripts/yt_callmins.py', 'scripts/yt_calls_mech.py', 'scripts/yt_condense.py', 'scripts/yt_episodes.py', 'scripts/yt_extract_calls.py', 'scripts/yt_frames_F.py', 'scripts/yt_frames_batch.py', 'scripts/yt_get_subs.sh', 'scripts/yt_get_subs2.sh', 'scripts/yt_grab.py', 'scripts/yt_inventory.py', 'scripts/yt_inventory_final.py', 'scripts/yt_ocr.py', 'scripts/yt_prefilter.py', 'scripts/yt_review_dump.py', 'scripts/yt_sample_index.py', 'scripts/yt_score.py', 'scripts/yt_score_all.py', 'scripts/yt_section.py', 'scripts/yt_subs2txt.py', 'results/yt_by_group.csv', 'results/yt_calls_scored.csv', 'results/yt_disc_candidates.csv', 'results/yt_disc_feature_contrast.csv', 'results/yt_disc_impute_medians.json', 'results/yt_disc_model.json', 'results/yt_disc_taken_vs_skipped_outcomes.csv', 'results/yt_disc_trader_entries.csv', 'results/yt_random_bench.csv', 'results/yt_review_adjudicated.csv', 'results/yt_stream_inventory.csv', 'results/yt_summary.csv', 'results/yt_trading_day_coverage.csv', 'results/yt_vs_selflog.csv'] def etag(k): try: return s3.head_object(Bucket=B,Key=k)['ETag'].strip('"') except s3.exceptions.ClientError: return None st={'new':0,'skip':0,'versioned':0} for f in sorted(files): p=f'{L}/{f}'; md=hashlib.md5(open(p,'rb').read()).hexdigest(); base,ext=os.path.splitext(f); v=1 while True: k=P+(f if v==1 else f'{base}-v{v}{ext}'); e=etag(k) if e is None: s3.upload_file(p,B,k); st['new' if v==1 else 'versioned']+=1; break if e==md: st['skip']+=1; break v+=1 print(st,'files',len(files))