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?
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