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 this command to go through all my files in my Music directory, and all subdirectories, and replace any square brackets in the file name with rounded brackets:

find /home/Music/ -depth -name "* *" -execdir rename 's/\[/\(/g' "{}" \;

But it doesn't work. It doesn't return any errors, it just doesn't make the replacements.

I thought I properly escaped the characters. Where am I going wrong?

Also, eventually I"ll want to replace curly brackets, {}, with rounded brackets , (), as well. Just thought I'd mention that now in case curly brackets came with yet more complications.

share|improve this question
1  
This should work as long as you have files with spaces in their names. What *nix are you on? –  terdon Apr 7 '13 at 4:11
    
Would you mind showing some sample directory data in this question? –  slm Apr 7 '13 at 4:36
    
Try adding -v (and optionally -n) to the rename part to see what is it doing. Also, you might need to modify the s/// option to be s///g to replace all matched characters, not only the first one it encounters. –  zorlem Apr 7 '13 at 11:27
    
rename is not a standard tool, so the various implementations have different syntax. Have you checked that you use the right syntax? –  manatwork Apr 7 '13 at 11:29
    
@terdon: That was my mistake. I totally forgot "* *" would look for files with spaces in the name, whereas what I need to do is "*[*". If you convert your comment to an answer I'll mark you correct. –  Dave M G Apr 7 '13 at 15:23
add comment

3 Answers 3

up vote 1 down vote accepted

The only reason I can see why it wouldn't work is if there are no files with spaces in their names. "* *" will only match if the filename has a space.

If you want to find files whose name contains square brackets, do

find /home/Music/ -depth -name "*[*" -execdir rename 's/\[/\(/g' "{}" \;
share|improve this answer
    
-name '*\[*' or -name '*[[]*' would be more portable. –  Stéphane Chazelas Apr 7 '13 at 19:19
add comment

The following should work:

for i in `find o -type f`; do new="${i/\[/(}" ; if [ "${i}" != "${new}" ]; then mv ${i} ${new} ; echo "Moving ${i} to ${new}"; fi ; done

If the file names contain spaces, try the following:

OLDIFS=${IFS} ; IFS=$(echo -en "\n\b") ; for i in `find o -type f`; do new="${i/\[/(}" ; if [ "${i}" != "${new}" ]; then mv ${i} ${new} ; echo "Moving ${i} to ${new}"; fi ; done; IFS=${OLDIFS}
share|improve this answer
    
You're using command substitution without setting IFS (though the OP was explicitly wanting to rename files with spaces in their name) ${i/../} is to replace one occurrence while the OP used the g flag, you forgot to quote some variables. That won't work properly if directory names contain [ –  Stéphane Chazelas Apr 7 '13 at 15:04
    
Modified answer to handle spaces. –  devnull Apr 8 '13 at 7:41
add comment

There are two main rename implementations on Linux:

  • The one that comes with perl (which is probably the one you were expecting)
  • The one that comes with util-linux (probably the one you have).

The syntax for the one that comes with util-linux would be:

find ... -execdir rename '[' '(' {} +

However, that would only replace one occurrence of [.

perl's rename might be called prename on your system.

An alternative to rename is zsh's zmv. It would take care of descending directories depth first and avoid problems with collisions.

In zsh:

autoload zmv
zmv '(**/)(* *)' '$1${2//\[/(}'

And for converting both {} and [] to ():

zmv -n '(**/)(* *)' '$1${${2//[]\}]/)}//[[{]/(}'    
share|improve this answer
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.