I have a directory where some filenames have been wrongly named something .pdf rather than something.pdf. Is there a quick one liner I can use to delete the whitespace in the filenames.

I have tried find -name "* .pdf" -type f | rename 's/ //g'

but this did not work.

  • 2
    rename expects the file name as 2nd parameter, not as input. So instead of piping to it, use find's -exec parameter to call rename. But rename accepts multiple file name parameters, so if recursion in subdirectories is not needed, just rename 's/ //g' *\ .pdf.
    – manatwork
    Apr 8, 2013 at 12:42
  • Thanks for the tip. I couldn't get rename 's/ //g' *\ .pdf but have used rename ' ' '' *.pdf instead.
    – moadeep
    Apr 8, 2013 at 12:47
  • 2
    So your rename implementation is the one from the util-linux package. Based on the syntax you used in the question looked like it's the one which comes with Perl.
    – manatwork
    Apr 8, 2013 at 12:51

2 Answers 2


In zsh, this is easily done with the zmv function. Put autoload -U zmv in your ~/.zshrc, or run this once in your shell, then:

zmv '* .pdf' '${f// /}'

This removes all spaces from the file name. If you only want to remove the one before the .pdf extension:

zmv '* .pdf' '${f# .pdf}.pdf'

or using parentheses to delimit groups that can be used as backreferences:

zmv '(*) .pdf' '$1.pdf'

If you want to act in subdirectories as well:

zmv '**/* .pdf' '${f# .pdf}.pdf'

or (note that you have to use (**/), not (**)/):

zmv '(**/)(*) .pdf' '$1$2.pdf'

Under Linux, with or without zsh, if there is only this one spurious space in the file names:

rename \ .pdf .pdf *\ .pdf

or, if there's only this one space in the original names:

rename ' ' '' *\ .pdf

If you want to act in subdirectories as well, in ksh93 ≥o+ or bash ≥4, you can use ** to match files in subdirectories. In bash, you need to run shopt -s globstar first (put this line in your ~/.bashrc) and set -o globstar in ksh93.

rename \ .pdf .pdf **/*\ .pdf

Beware that bash follows symlinks when recursing directories.

Without the benefit of **, you can use find to recurse.

find . -name '* .pdf' -exec rename ' .pdf' .pdf {} +

Under Debian and derivatives (including Ubuntu) and most non-Linux systems that ship with perl, the rename command is a different one, which takes a Perl expression as an argument instead of a string to replace and a replacement string. Either use rename.ul in the commands above (under Debian and derivatives), or with the Perl rename:

rename 's/ \.pdf$/.pdf/' -- *\ .pdf    # strip the space before the extension
rename 's/ //g' -- *\ .pdf             # strip all spaces
  • 1
    +1 for being so thorough and covering more than one tool. All of your answers are incredible, by the way. I've learned a lot from them in the past few months.
    – user26112
    Apr 10, 2013 at 2:31
  • Note that the rename ... *\ .pdf ones will fail if there are pdf files whose name starts with - unless POSIXLY_CORRECT= is in the environment. You need the -- to avoid it, but that should go before the non-option arguments. Jan 25, 2014 at 23:22

This will protect against accidental overwrite, if that's important.

for i in $(find . -name '* .pdf')
  mv -i "$i" "${i% .pdf}.pdf"

If you run this in an interactive shell you might want to exit it immediately since you change IFS.

You must log in to answer this question.

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