Take the 2-minute tour ×
Server Fault is a question and answer site for professional system and network administrators. It's 100% free, no registration required.

I have a bunch of files who's filename follows the pattern 'filename.ext'. eg:

filename .ext

I would like to rename all of these to remove the space before the .ext. eg:

filename.ext

I can find them all using

find * -type f -name'* .*'

but how can I then rename all these files?

share|improve this question

4 Answers 4

up vote 4 down vote accepted

Make a file named "renamethis.sh". Its contents should be:

#!/bin/bash
mv "$1" "$(echo $1 | sed 's/ \././')"

Set the executable bit: chmod a+x renamethis.sh. Then, run something like:

find /path/to/dir -name '* .*' -type f -print0 | xargs -0L 1 /path/to/renamethis.sh

YMMV, no warranty express or implied, etc.

FWIW, the spaces are what makes this strange; as long as you don't have other oddball characters in the files names, you're good to go with this approach. If you do, you may want to consider something like a scandir/readdir loop in Perl or PHP, but the above script is the first thing that came to mind.

share|improve this answer
    
Thanks that worked a treat. –  Rich Apr 28 '11 at 3:25
    
Instead of using a custom script I suggest you to use the command rename which comes on every major distro. Check it's man page. –  hmontoliu Apr 28 '11 at 10:40
2  
For "rename" to work, you'd have to have a complete list of all the extensions. So something like: for ext in $(find /path/to/dir -name '* .*' -type f | sed 's/.* \.//;s/ .*//'); do rename " .$ext" .$ext /path/to/dir/*\ .$ext; done. Without testing, though, not sure if rename is going to play nice with that glob, and it seems like a roundabout way to use a specific tool, so I think I still prefer my approach in circumstances where there's more than one extension that needs to be changed. –  BMDan Apr 28 '11 at 18:23
2  
for exaple given this tree structure and several files with "any number of spaces prior to a dot extension" as follows: mkdir -p a/deep/tree touch a/'foo .ext' a/deep/'bar .otherext' a/deep/tree/'x .foo' You can find and rename all of them with rename: find a/ -name '* .*' -exec rename -v 's/ *\././' '{}' \;' resulting in: a/deep/tree/x .foo renamed as a/deep/tree/x.foo a/deep/bar .otherext renamed as a/deep/bar.otherext a/foo .ext renamed as a/foo.ext –  hmontoliu Apr 28 '11 at 20:40
1  
@hmontoliu I see what you did there. Neat approach! :) –  BMDan Apr 28 '11 at 22:37

This should do it for you.

#!/bin/bash

OLDIFS=${IFS}
IFS=$'\n'

for file in `find * -type f -name '* .*'`; do
 _ext=`echo ${file} | cut -d '.' -f 2-`
 _filename=`echo ${file} | cut -d ' ' -f 1`
 mv "${file}" ${_filename}.${_ext}
done

IFS=${OLDIFS}
share|improve this answer
    
Thanks for your answer. However the cut command didn't find the extension correctly when there were other spaces or dots in the filename. But thanks for responding. –  Rich Apr 28 '11 at 3:26
    
No problem, glad you found a solution though. His is definitely more elegant than mine. –  rfelsburg Apr 28 '11 at 3:36

In one line:

find -depth -name '* .*' -print0 |
perl -wn0e '$orig = $_; s/\s+\././g; rename($orig, $_) or warn "$orig: $!\n"'

Highlights:

  • no problem with quoting spaces in filenames
  • no problem with filenames starting with a dash
  • fast: only two processes started in parallel
  • handles directories correctly
share|improve this answer

I see that you've already solved your immediate problem, but in the future you might want to consider using mmv.

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.