Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

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.

share|improve this question
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 '13 at 12:42
    
Thanks for the tip. I couldn't get rename 's/ //g' *\ .pdf but have used rename ' ' '' *.pdf instead. –  moadeep Apr 8 '13 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 '13 at 12:51

2 Answers 2

up vote 5 down vote accepted

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
share|improve this answer
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. –  paraxor Apr 10 '13 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. –  Stéphane Chazelas Jan 25 at 23:22

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

IFS=$'\n'
for i in $(find . -name '* .pdf')
do
  mv -i "$i" "${i% .pdf}.pdf"
done

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

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.