Home > database >  How to rename files recursively to hex base 16
How to rename files recursively to hex base 16

Time:12-24

How to rename files in different folders (but all folders are under one folder)(without considering what's their names) to hex base 16, recursively?

example of folders hierarchy

So, when it goes to the next folder, it remembers what was the previous naming it did and it continues from there.


For example(different than the screenshot):
Folder1: 1.jpg, 1_A.jpg, ... 10th_blah.jpg
Folder2: 1.jpg, ..., 2000th_text1.jpg

will become ->
FolderAllTogether: 1.jpg, 2.jpg, ..., A.jpg, B.jpg, ..., 7D0.jpg


The solution could be in javascript, bash, python, or any other script languages I can run easily on macOS.


My code:

const fs = require('fs')
const path = require('path');
const dir = path.resolve(__dirname, 'ImagesSuperTemp');
let i = 0

function renameFilesRecursive(dir, from, to) {

    fs.readdirSync(dir).forEach(it => {
        const itsPath = path.resolve(dir, it);
        const itsStat = fs.statSync(itsPath);

        if (itsPath.search(from) > -1) {
            console.log(`${i} : rename ${from} to ${to}`);
            fs.renameSync(itsPath, itsPath.replace(from, to))
            i = i   1
        }

        if (itsStat.isDirectory()) {
            renameFilesRecursive(itsPath.replace(from, to), from, to)
        }
    })
}

renameFilesRecursive(dir, /\*.jpg$/, `${i.toString(16)}.jpg`);

But it does nothing!

CodePudding user response:

There is below a bash script. Change the values of dest_dir and source_dir

Do not forget to make it executable with chmod x flattener.sh

#!/bin/env bash

dest_dir="/var/tmp/flat-files"
source_dir="parent-dir"

if [ ! -d "${dest_dir}" ] ; then
  mkdir -p "${dest_dir}"
fi

if [ ! -f "${dest_dir}"/index.dat ] ; then 
  printf "1" > "${dest_dir}"/index.dat || exit 1
fi

find "${source_dir}" -type f -print0 |\
  xargs -0 bash -c ' \
    for filename ; do \
      index=$(cat '"${dest_dir}"'/index.dat) ;\
      printf "%d" $((index 1)) > '"${dest_dir}"'/index.dat ;\
      if [[ "${filename}" =~ [.] ]] ; then \
        extension=."${filename##*.}" ;\
      else \
        extension="" ;\
      fi ;\
      mv -vu "${filename}" '"${dest_dir}"'/$(printf "%X" $index)"${extension}" ;\
    done' flattener

CodePudding user response:

Python solution

(throws you an error if you want to rename a file which already exists, e.g. you are processing image 5.jpg while your counter is at 3, but 3.jpg exists already; Could avoid that with a try except clause but then you do not have pictures always incremented by 1 - not sure what you require):

import os
counter = 1
for r, d, f in os.walk(r"Images"):  # can also put a full path here
    for name in f:
        # first argument here is full path to the image
        # second argument is the path   the hex number of the counter   the extension of the file
        os.rename(r   os.sep   name, r   os.sep   hex(counter).lstrip("0x")   os.path.splitext(name)[-1])
        counter  = 1

Edit

I further documentated the code, added a status-message and noticed that you want uppercase hex file names:

import os
counter = 1
for r, d, f in os.walk(r"Images"):  # can also put a full path here
    for name in f:
        # full path to original image
        original_fn = r   os.sep   name

        # path   hex number of counter   extension of file
        new_fn = r   os.sep   hex(counter).lstrip("0x").upper()   os.path.splitext(name)[-1]  

        # rename, status print, incrementing counter
        os.rename(original_fn, new_fn)
        print(f"Renamed {original_fn} > {new_fn}")
        counter  = 1

Edit 2

Here is a solution to first rename all files to temporary files with random strings attached, and after that rename all of them to hex numbers based on a counter. Hope that solves your problems:

import os
import random
import string

for r, d, f in os.walk(r"Images"):
    for name in f:
        rnd_string = ''.join(random.SystemRandom().choice(string.ascii_letters   string.digits) for _ in range(12))
        original_fn = r   os.sep   name
        new_fn = r   os.sep   rnd_string   name
        os.rename(original_fn, new_fn)
        print(f"Temp. rename {original_fn} > {new_fn}")

counter = 1
for r, d, f in os.walk(r"Images"):  # can also put a full path here
    for name in f:
        original_fn = r   os.sep   name
        new_fn = r   os.sep   hex(counter).lstrip("0x").upper()   os.path.splitext(name)[-1]  
        os.rename(original_fn, new_fn)
        print(f"Final rename {original_fn} > {new_fn}")
        counter  = 1
  • Related