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.
Install renameutils
and use qmv
with your favorite text editor.
qmv
loads all names in your editor and when you save and close it applies your changes to the actual files. If the changes are inconsistent (e.g. two files get the same name) it will abort without touching anything. It also handles circular renames correctly.
I usually do:
$ qmv -f do
so that it shows just one column of names (do: destination-only). Here's how it looks:
If you combine it with the multiple cursors of SublimeText, Atom or Visual Studio Code, it makes a very nice and powerful tool for bulk renaming. For instance, for Atom, you would do EDITOR="atom -w" qmv -f do
.
Best Answer
You can do that with
find
as follows:This only prints the renaming actions, if it shows what you want remove the
-n
option.Explanations
-depth
– letsfind
process from bottom to top, renaming files before their parent directories-name ".*"
– letsfind
search for files (everything is a file) beginning with a dot – the dot is literal here, as this is not a regular expression-execdir … +
– execute…
in the matched file‘s directoryrename 's|/\.|/|' {}
– replace the first occurence of “/.” from the matched file’s path (find
’s placeholder for which is{}
) with “/”, essentially removing the dot from the beginning of the filenameThis would be e.g.
rename 's|/\.|/|' ./.hiddenfile1
in your case, this would be renamed to./hiddenfile1
.Example run
Usage in a script
In a script you can simply use positional parameters instead of the path, it may be relative or absolute – just remember to quote correctly: