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.

How do you rename all files/subdirs in the current folder?

Lets say, I have many files and subdirs that are with spaces and I want to replace all the spaces with an underscore.

File 1
File 2
File 3
Dir 1
Dir 3

should be renamed to

File_1
File_2
File_3
Dir_1
Dir_3
share|improve this question
add comment

6 Answers

up vote 15 down vote accepted

If you need to rename files in subdirectories as well, then you can do

find /search/path -depth -name '* *' \
    -execdir bash -c 'mv "$1" "${1// /_}"' _ {} \;

Thank to @glenn jackman for suggesting -depth option for find and to make me think.

share|improve this answer
    
You would need to use find -maxdepth 1 to do exactly what the OP asked about operating on the current folder. –  Caleb Aug 20 '11 at 6:34
1  
Use find's -depth option, and you can get rid of the sort. –  glenn jackman Aug 20 '11 at 14:52
    
@glenn jackman: thank you, I now understand my solution was wrong. –  enzotib Aug 20 '11 at 15:19
1  
Change -name '* *' to -name '*_*' and change "${1// /_}" to "${1//_/.}" –  enzotib Jan 24 '13 at 19:41
1  
@kroiz: it is called "Pattern substitution". You could find it in bash's man page. –  enzotib Jan 30 '13 at 9:31
show 3 more comments

You can use rename for this:

cd /path/to/dir
rename ' ' _ *\ *

This will find all files and directories space in the name and replace the space with an underscore. Since it uses glob file matching you need to be in the right directory to start with.

If you want to do recursive matches you can, but you might have to execute the rename a couple times to catch any items in directories that themselves got renamed:

cd /path/to/dir
shopt -s globstar
rename ' ' _ **/*\ *
!!; !!
share|improve this answer
1  
rename will rename the specified files by replacing the first occurrence of from in their name by to.” So this will only work for files with a single space in their name. (You could call rename in a loop, but it's not really the right tool here.) –  Gilles Aug 21 '11 at 0:54
add comment

In any shell, you can loop over the files whose name contains a space. Replacing the spaces with underscores is easy in bash, ksh and zsh with the ${VARIABLE//PATTERN/REPLACEMENT} construct.

for x in *" "*; do
  mv -- "$x" "${x// /_}"
done

On Debian, Ubuntu and derivatives, you can use the Perl rename (other distributions ship a different program as rename, and that program isn't helpful here).

rename 's/ /_/g' *

An obligatory zsh solution:

autoload zmv
zmv '(*)' '${1// /_}'

An obligatory POSIX solution:

for x in *" "*; do
  y=$(printf %sa "$x" | tr " " "_")
  mv -- "$x" "${y%a}"
done
share|improve this answer
add comment

Another option would be mmv, if installed.

mmv \*\ \* \#1_#2
share|improve this answer
    
This only changes the first space into a _, it doesn't work names with multiple spaces. –  Gilles Aug 21 '11 at 0:58
    
Oups, you are right. Sorry for the confusion. –  glglgl Aug 21 '11 at 4:41
add comment

If you're not a flash at regular expressions (I'm not!), and you can run applications designed for kde (either you use kde - k desktop or you have it's libraries installed), then krename is a great graphical utility that lets you see the before and after before you commit to the changes. It has a number of simple transformations as options and also supports regular expressions. You can even combine several sequential transformations into one rename so you don't have to design a single complex transform that does it all at once. It also has an option to continue renaming the same files after a rename has been applied.

I don't use it that often, but when I do, it really gets the job done quickly and easily. It really comes in handy when renaming various downloaded media files so you can manage them uniformly on your system. It helps to download the krename manual separately so you can refer to it while using the program.

http://www.krename.net/

share|improve this answer
add comment

On Debian/Ubuntu, building upon the answers of Caleb and Gilles, this is what worked for me to rename files recursively:

cd /path/to/dir
shopt -s globstar
rename 's/ /_/g' **

Note: To preview what files would be renamed and how, use the -n switch with rename:

rename -n 's/ /_/g' **

Another note: setting globstar makes ** match files in all subdirectories, so if only current directory is desired, don't set globstar or use * instead of **.

One more note: The rename command needs to be run more than once for files with multiple occurrences of the search term.

share|improve this answer
    
That only works if directories don't contain spaces. (a rename of a b/c d to a_b/c_d wouldn't work, you'd need first to rename a b/c d to a b/c_d, and then a b to a_b). –  Stephane Chazelas Dec 20 '13 at 16:15
    
@Stephane: Does it mean to run the same rename command twice? –  Markus Dec 20 '13 at 16:19
    
Well, more like as many times as there are nested levels of directories with spaces. Ideally, you want to traverse the directory depth first, and convert only the basename of the file like in the accepted solution. Also note that bash's ** excludes dotfiles and traverses symlinks. –  Stephane Chazelas Dec 20 '13 at 16:26
add comment

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.