Bash Script sed command not working correctly with file passed through command line

Viewed 830

Problem

As I am trying to write a script to rename massive files according to some regex requirement, the command work ok on my iTerm2 succeeds but the same command fails to do the work in the script.

Plus some of my file names includes some Chinese and Korean characters.(don't know whether that is the problem or not)

code

So My code takes three input: Old regex, New regex and the files that need to be renamed.

Here is not code:

#!/bin/bash

# we have less than 3 arguments. Print the help text:
if [ $# -lt 3 ] ; then
  cat << HELP
ren -- renames a number of files using sed regular expressions USAGE: ren 'regexp'
'replacement' files...

EXAMPLE: rename all *.HTM files into *.html:
ren 'HTM' 'html' *.HTM

HELP
  exit 0
fi

OLD="$1"
NEW="$2"
# The shift command removes one argument from the list of
# command line arguments.
shift
shift
# $@ contains now all the files:
for file in "$@"; do
  if [ -f "$file" ] ; then
    newfile=`echo "$file" | sed "s/${OLD}/${NEW}/g"`
    if [ -f "$newfile" ]; then
      echo "ERROR: $newfile exists already"
    else
      echo "renaming $file to $newfile ..."
      mv "$file" "$newfile"
    fi
  fi
done

I register the bash command in the .profile as:

alias ren="bash /pathtothefile/ren.sh"

Test

The original file name is "제01과.mp3" and I want it to become "第01课.mp3".

So with my script I use:

$ ren "제\([0-9]*\)과" "第\1课" *.mp3

And it seems that the sed in the script has not worked successfully.

But the following which is exactly the same, works to replaces the name:

$ echo "제01과.mp3" | sed s/"제\([0-9]*\)과\.mp3"/"第\1课\.mp3"/g

Any thoughts? Thx

Print the result

I have make the following change in the script so that it could print the process information:

newfile=`echo "$file" | sed "s/${OLD}/${NEW}/g"`
echo "The ${file} is changed to ${newfile}"

And the result for my test is:

The 제01과.mp3 is changed into 제01과.mp3
ERROR: 제01과.mp3 exists already

So there is no format problem.

Updating(all done under bash 4.2.45(2), Mac OS 10.9)

Testing

As I try to execute the command from the bash directly. I mean with the for loop. There is something interesting. I first stored all the names into a files.txt file using:

$ ls | grep mp3 > files.txt

And do the sed and bla bla. While single command in bash interactive mode like:

$ file="제01과.mp3"
$ echo $file | sed s/"제\([0-9]*\)과\.mp3"/"第\1课\.mp3"/g

gives

第01课.mp3

While in the following in the interactive mode:

files=`cat files.txt`
for file in $files
do
    echo $file | sed s/"제\([0-9]*\)과\.mp3"/"第\1课\.mp3"/g
done

gives no changes!

And by now:

echo $file

gives:

$ 제30과.mp3

(There are only 30 files)

Problem Part

And I tried the first command which worked before:

$ echo $file | sed s/"제\([0-9]*\)과\.mp3"/"第\1课\.mp3"/g

It gives no changes as:

$ 제30과.mp3

So I create a new newfile and tried again as:

$ newfile="제30과.mp3"
$ echo $newfile | sed s/"제\([0-9]*\)과\.mp3"/"第\1课\.mp3"/g

And it gives correctly:

$第30课.mp3

WOW ORZ... Why! Why ! Why! And I try to see whether file and newfile are the same, and of course, they are not:

if [[ $file == $new ]]; then
    echo True
else
    echo False
fi

gives:

False

My guess

I guess there are some encoding problems , but I have found non reference, could anyone help? Thx again.

Update 2

I seem to understand that there are a huge difference between string and the file name. To be specific, it I directly use a variable like:

file="제30과.mp3"

in the script, the sed works fine. However, if the variable was passed from the $@ or set the variable like:

file=./*mp3

Then the sed fails to work. I don't know why. And btw, mac sed has no -r option and in ubuntu -r does not solve the question I mention above.

2 Answers
Related