If you have access to perl rename, (installed by default as rename
on Debian-based systems, available as perl-rename
on many others), you could run:
rename 's/.*/lc($&)/e; s/(^| )./uc($&)/ge' *
Explanation:
The rename
program will run a perl expression on each of its input file names. Here, the first substitution operation (s///
) will replace everything (.*
) with itself ($&
is whatever was matched) but lower cased (lc($&)
). The second, will match every character that's after a space or at the beginning of the file name ((^| )
) and replace it with its upper cased version (uc($&)
).
Run with the -n
flag to test without making any changes:
$ rename -n 's/.*/lc($&)/e; s/ ./uc($&)/ge' *
rename NOT A FILE.ogg not A File.ogg
rename sensitive lalala.doc sensitive Lalala.doc
rename SomeThing.TXT something.txt
You could also use a shell loop and perl:
for f in *; do
mv "$f" "$(perl -lpe 's/.*/lc($&)/e; s/(^| )./uc($&)/ge' <<<"$f")"
done
This is the same command as in the rename
above, only we feed it each file in the directory and use command substitution to rename.
You could easily modify this to avoid overwriting existing files:
for f in *; do
target="$(perl -lpe 's/.*/lc($&)/e; s/(^| )./uc($&)/ge' <<<"$f")";
[ -e "$target" ] &&
echo "File \"$target\" exists, skipping \"$f\"" ||
mv "$f" "$target";
done
rename
is. Is it the perl one on Arch or the BSD one?/usr/bin/rename
isutil-linux
.perl-rename
is a separate command with a package of the same name.perl-rename
, you can use my answer. On my Debian, it claims to warn before overwriting but doesn't actually do so. I also added a shell version that can avoid overwriting.