To use the script below, you do not need more than the ability to paste :)
How to use
- Paste the script below into an empty file, save it as (e.g.)
rename_title.py
- make it executable (for convenience reasons)
chmod u+x rename_title.py
Run it with the directory to rename as argument:
/path/to/rename_title.py <directory/to/rename>
The script
#!/usr/bin/env python3
import os
import sys
import shutil
directory = sys.argv[1]
skip = ["a", "an", "the", "and", "but", "or", "nor", "at", "by", "for", "from", "in", "into", "of", "off", "on", "onto", "out", "over", "to", "up", "with", "as"]
replace = [["(", "["], [")", "]"], ["{", "["], ["}", "]"]]
def exclude_words(name):
for item in skip:
name = name.replace(" "+item.title()+" ", " "+item.lower()+" ")
# on request of OP, added a replace option for parethesis etc.
for item in replace:
name = name.replace(item[0], item[1])
return name
for root, dirs, files in os.walk(directory):
for f in files:
split = f.find(".")
if split not in (0, -1):
name = ("").join((f[:split].lower().title(), f[split:].lower()))
else:
name = f.lower().title()
name = exclude_words(name)
shutil.move(root+"/"+f, root+"/"+name)
for root, dirs, files in os.walk(directory):
for dr in dirs:
name = dr.lower().title()
name = exclude_words(name)
shutil.move(root+"/"+dr, root+"/"+name)
Examples:
a file > A File
a fiLE.tXT > A File.txt
A folder > A Folder
a folder > A Folder
And more complex, excluding ["a", "an", "the", "and", "but", "or", "nor", "at", "by", "for", "from", "in", "into", "of", "off", "on", "onto", "out", "over", "to", "up", "with", "as"]
:
down BY the rIVER for my uncLE To get water.TXT
becomes:
Down By the River for My Uncle to Get Water.txt
etc, it simply makes all files and folders (recursively) Title Case, extensions lower case.
EDIT: I have added all articles, conjunctions and prepositions that do not need to be capitalized according to the capitalization rules for song titles.
Best Answer
From GNU Bash manual - The Shopt Builtin:
So, in a pure-Bash fashion, I'd do:
${f%/*}
: will expand to what's left after having removed everything until a/
character is found (including the/
character) from$f
, starting from the end (basically, it will expand to$f
's base path), or to the value of$f
if the pattern didn't match (e.g., in case of a.png
file in the current working directory)base_path="${f%/*}"
and precedingmv "${f}" "${base_path}${RANDOM}-${RANDOM}-${RANDOM}.png"
will set$base_path
to an empty string if the value of$base_path
is stringwise-equal to$f
, or will add a trailing/
to$base_path
otherwiseIn Zsh, you'd be able to do the exact same without setting any shell option:
If you want
$RANDOM
to be something other than a number in the 0-32767 range, you can leverage/dev/urandom
to generate custom random values.For example, to generate a random alphanumeric string of length 5:
tr -dc '[:alnum:]' </dev/urandom
: will read undefinetly from/dev/urandom
, printing only characters in the character set[:alnum:]
(equivalent to[0-9A-Za-z]
, hence printing only digits and upper/lower-case alphabetical characters)fold -w5
: will split the output oftr
in lines of length 5head -n1
: will print the first line, immediately closing the pipeSee
man tr
for more options.Applying the above to your command (making
tr -dc '[:alnum:]' </dev/urandom | fold -w5 | head -n1
into a function, to avoid awkwardly calling it 3 times and setting 3$rand_n
variables):