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'm trying to remove characters from a file name.

files

#ls
Peter, Paul & Mary - The Very Best of Peter, Paul and Mary (AutoFlac).flac
Peter, Paul & Mary - The Very Best of Peter, Paul and Mary (AutoFlac).log
Peter, Paul & Mary - The Very Best of Peter, Paul and Mary.cue

What I want for output:

#ls
Peter, Paul & Mary - The Very Best of Peter, Paul and Mary.cue
Peter, Paul & Mary - The Very Best of Peter, Paul and Mary.flac
Peter, Paul & Mary - The Very Best of Peter, Paul and Mary.log

script

#!/bin/bash
SUFFIX="(AutoFLAC)"
#search directory for file with a suffix of (AutoFLAC)
for entry in *$SUFFIX*
do
   #remove a leading space and (AutoFLAC) from the file name
   FILENAME=`echo $entry | sed 's/ (AutoFLAC)//'`
   echo "$entry"
   echo "$FILENAME"
   #change the old file name for the new file name
   mv  "$entry" "$FILENAME"
 done

If I add -x, it works.

Mac-Attack:edit-file-names $ ./edit-file-names1.sh 
+ SUFFIX='(AutoFLAC)'
+ for entry in '*$SUFFIX*'
++ echo Peter, Paul '&' Mary - The Very Best of Peter, Paul and Mary '(AutoFLAC).flac'
++ sed 's/ (AutoFLAC)//'
+ FILENAME='Peter, Paul & Mary - The Very Best of Peter, Paul and Mary.flac'
+ echo 'Peter, Paul & Mary - The Very Best of Peter, Paul and Mary (AutoFLAC).flac'
Peter, Paul & Mary - The Very Best of Peter, Paul and Mary (AutoFLAC).flac
+ echo 'Peter, Paul & Mary - The Very Best of Peter, Paul and Mary.flac'
Peter, Paul & Mary - The Very Best of Peter, Paul and Mary.flac
+ mv 'Peter, Paul & Mary - The Very Best of Peter, Paul and Mary (AutoFLAC).flac' 
'Peter, Paul & Mary - The Very Best of Peter, Paul and Mary.flac'
+ for entry in '*$SUFFIX*'
++ echo Peter, Paul '&' Mary - The Very Best of Peter, Paul and Mary '(AutoFLAC).log'
++ sed 's/ (AutoFLAC)//'
+ FILENAME='Peter, Paul & Mary - The Very Best of Peter, Paul and Mary.log'
+ echo 'Peter, Paul & Mary - The Very Best of Peter, Paul and Mary (AutoFLAC).log'
Peter, Paul & Mary - The Very Best of Peter, Paul and Mary (AutoFLAC).log
+ echo 'Peter, Paul & Mary - The Very Best of Peter, Paul and Mary.log'
Peter, Paul & Mary - The Very Best of Peter, Paul and Mary.log
+ mv 'Peter, Paul & Mary - The Very Best of Peter, Paul and Mary (AutoFLAC).log' 'Peter, Paul & Mary - The Very Best of Peter, Paul and Mary.log'
Mac-Attack:edit-file-names $ ls
Peter, Paul & Mary - The Very Best of Peter, Paul and Mary.cue
Peter, Paul & Mary - The Very Best of Peter, Paul and Mary.flac
Peter, Paul & Mary - The Very Best of Peter, Paul and Mary.log

Without the -x:

Mac-Attack:edit-file-names $ ./edit-file-names2.sh 
*(AutoFLAC)*
*(AutoFLAC)*
mv: rename *(AutoFLAC)* to *(AutoFLAC)*: No such file or directory

Insights, thoughts?

share|improve this question
    
@Mat, you just beat me to it. I was literally working on it right now :) –  rahmu Feb 5 '12 at 21:25
    
What's -x? Apologies for bugging you, but I've never heard of it. –  njsg Feb 5 '12 at 21:34
    
@njsg: see man set, "The shell shall write to standard error a trace for each command after it expands the command and before it executes it...." –  Mat Feb 5 '12 at 21:37
add comment

1 Answer

There's evidently something odd going on around case-insensitive wildcard matching. According to the ls output, the file names contain (AutoFlac), whereas your script looks for (AutoFLAC). Unix tools traditionally consider two file names to be the same only if they're byte-for-byte identical; there's nothing built-in for case-insensitive matching. Bash seems to behave inconsistently on a case-insensitive filesystem, this may be a bug.

Your script would be more robust if you used double quotes around variable substitutions. If you don't, bash (like other shells) performs globbing on the result of the variable substitution. This may be the source of your trouble. Always put double quotes around variable substitutions and command substitutions: "$foo", "$(foo)" unless you know you want to perform word splitting and globbing on the result. Also your script with the missing double quotes wouldn't work on some file names, e.g. with whitespace sequences that aren't a single space.

I also recommend doing the text substitution inside the shell, there's less risk of mangling file names that way.

SUFFIX="(AutoFlac)"
for entry in *"$SUFFIX"*; do
  target=${entry/ $SUFFIX/}
  mv -- "$entry" "$target"
done

There's no way to force case-insensitive wildcard matching, but you can make your script ignore case by doing your own matching.

SUFFIX="(autoflac)"
for entry in *; do
  if [[ ${entry,,} = *$SUFFIX* ]]; then
    # Remove everything from the last space to the last .
    mv -- "$entry" "${entry% *}.${entry##*.}"
  fi
done
share|improve this answer
    
@forcefsck My reply was to the final version of your comment. I don't understand what you're getting at. –  Gilles Feb 6 '12 at 2:03
    
Nevermind. I'll delete this later. –  forcefsck Feb 6 '12 at 5:54
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.