I haven't had much success in finding a Linux version of namemangler, which I need to rename 1000 of files so they are readable on Windows.

Does anyone know of a Linux program that can do this?

If not, then a script might work as I only need to rename all files in a folder to, say, the first 16 characters. I suspect that the script route might be worth going down but not sure where to start.

  • 2
    You probably could write quickly a Python or Perl or Ocaml or Ruby script doing that.
    – Basile Starynkevitch
    Commented Feb 29, 2012 at 12:48
  • Why can't you just use a vfat filesystem, which allows long file names?
    – wnoise
    Commented Mar 1, 2012 at 6:28
  • 2
    Out of curiosity, how long are does names and what do they contain that they are not recognised by Windows?
    – Bobby
    Commented Mar 1, 2012 at 19:34

7 Answers 7


On Debian, Ubuntu and derivatives, if you enter man rename at a command prompt, you'll get the manual page for a rename utility that allows arbitrary Perl-like regular expression commands to be used in the renaming.

For example, this will shorten (by truncating) all files in the current directory to a length of five:

rename 's/^(.{5}).*/$1/' *

It works by capturing the first five characters then using that in the substitution, removing the rest.

Another example is to shorten filenames (sans extension) to five characters wile preserving the extension:

rename 's/^(.{5}).*(\..*)$/$1$2/' *

It captures two groups, the first being the first five character, the second being the extension. This would turn myCarefullyCraftedDocument.pdf into myCar.pdf.

Warning: Use this carefully, preferably on a copy of your directory, or by taking backups first. You have been warned!! At a bare minimum, use rename -n first, which will show you what would be done without actually doing it.

  • 1
    will this get rid of the prefix as in PDF? and what would happen to files with the same name once shorten?
    – Grimlockz
    Commented Feb 29, 2012 at 13:01
  • That particular example will, yes. You can write a regex to leave the extension alone. I'll update the answer. It also protects against overwriting files that already exist, so later renames will fail.
    – user14408
    Commented Feb 29, 2012 at 13:04
  • thanks for your help on this - I'm very thankful. I do have one slight issue if some of the pdfs will be renamed to 5 lets say what would happen to the PDF's it tries to rename with the same name? Is they a way we can just add a unique number onto all the ones with this is? see below ename -n 's/^(.{5}).*(\..*)$/$1$2/' * Annexes 123114345234525.pdf renamed as Annex.pdf Annexes 123114432452352.pdf renamed as Annex.pdf
    – Grimlockz
    Commented Feb 29, 2012 at 13:14
  • @Grimlockz, I don't think you can put that sort of intelligence into the rename regex itself. What you may need to do is write a script to wrap rename with that sort of intelligence, and that's better asked as a separate question so you'll get more people responding than just I.
    – user14408
    Commented Feb 29, 2012 at 13:19
  • @Grimlockz This is why you don't want to do everything in a regex. You'll be happier and better off writing a script that uses regexes. Commented Feb 29, 2012 at 13:26

You can move conflicted files to other directory:

for i in *

    if [ -e "$j" ]
        mv "$i" /path/to/rename/later
        mv "$i" "$j"

You can write a script to shorten file names and remove characters that Windows doesn't like in a few lines of bash. Warning, untested code, typed directly into my browser.

shopt -s dotglob extglob
for x in *; do
  y=${x//+([!-!#$%&'().0-9@A-Z^_`a-z{}~])/_}  # change all problematic characters to _
  if [[ $y = .* ]]; then y=_${y#.}; fi        # change dot files to begin with _
  y=${y:0:16}                                 # truncate names
  y=${y,,}                                    # convert to lowercase
  if [[ -e $y || $y =~ ^(aux|clock\$|com[0-9]|con|lpt[0-9]|nul|prn)(\.*)?$ ]]; then
    # The file exists or is a DOS/Windows reserved name.
    # Change foo.bar to foo~1.bar, foo~2.bar, ... (I ignore the length restriction here)
    if [[ $y =~ \. ]]; then
      prefix=${y%%.*}; suffix=.${y#*.}
      prefix=$y; suffix=
    while [[ -e $y ]]; do
  mv -- "$x" "$y"

If you need to recurse into subdirectories, call a shell script from find -depth -exec …. Or use zsh instead of bash; in zsh, **/*(od) expands to all the files under the current directory, recursively, with more deeply nested files first.


Shell/python/perl scripting for this kind of thing is just fine, but it seems like a gui app would be best for you, so I would recommend pyRenamer, which can do exactly what you want, among many other things (simple common operations via presets [getting rid of spaces, truncating filename from one point to another], simple search/replace, complicated regex, previewer, etc).

Your distribution might even have it in their software repository (Fedora does).


Some systems do not have the rename command, so as an alternative to paxdiablo's answer, here is how to do the same thing with mv.

for f in *.pdf; do 
    tmp=`echo $f | sed -r 's//^(.{5}).*(\..*)$/$1$2/'`
    mv -b ./"$f" ./"$tmp"

The -b flag on move creates a backup of files that would be deleted or overwritten. By changing the glob pattern in the for loop you can adjust what files it runs on, using * by itself to run on all files.

  • 1
    No need to use echo and a pipe (could be very expensive if you have a lot of files), use a heredoc or herestring instead.
    – Chris Down
    Commented Feb 29, 2012 at 13:48
  • 1
    @ChrisDown see here. According to the wiki article, the piped processes are forked, but it says nothing about running them in their own shells. Commented Feb 29, 2012 at 14:49
  • 1
    For example, notice the difference between eval 'echo $BASH_SUBSHELL' and eval 'echo $BASH_SUBSHELL' | cat.
    – Chris Down
    Commented Feb 29, 2012 at 15:36
  • 2
    I just did a quick test, timeing a loop using echo $i | sed and another using sed ... <<<$i, and the herestring took about 2/3 the time of the echo.
    – Kevin
    Commented Feb 29, 2012 at 19:39
  • 1
    @SpencerRathbun Yes. << starts a here<i>doc</i>, which is multi-line and requires delimiters. <<< creates a here<i>string</i>, which just takes one variable/string. Try it out, var=abc // cat<<<$var // cat <<$var.
    – Kevin
    Commented Feb 29, 2012 at 19:53

If you need to experiment with renaming files and happen to have KDE libraries installed on your system (or don't mind adding them), check out krename.

It allows you to do quite a few simple renaming tasks directly with its tools and also allows regular expressions for more complicated situations.

It shows you a preview of the renamed files as you build the renaming conditions. It also allows you to rename the same files again which is helpful if you want to do something complicated where doing it in stages would reduce the complexity of each stage to something you can figure out quickly.

for file in *; do
    mv "$file" $(echo "$file" | sed -e 's/[^A-Za-z0-9._-]/_/g')
done &

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .