Bash Script sed命令与通过命令行传递的文件无法正常工作

时间:2013-12-14 04:42:11

标签: regex bash unicode sed

问题

当我尝试编写一个脚本来根据一些正则表达式要求重命名海量文件时,我的iTerm2上的命令正常工作成功,但是相同的命令无法在脚本中完成工作。

另外我的一些文件名包括一些中文和韩文字符。(不知道是否有问题)

所以我的代码有三个输入:旧正则表达式,新正则表达式和需要重命名的文件。

这不是代码:

#!/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

我将 .profile 中的bash命令注册为:

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

测试

原始文件名是“제01과.mp3”,我希望它成为“第01课.mp3”。

所以我用我的脚本:

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

似乎脚本中的 sed 无法成功运行。

但以下内容完全相同,可以取代名称:

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

有什么想法? THX

打印结果

我在脚本中进行了以下更改,以便它可以打印进程信息:

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

我的测试结果是:

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

所以没有格式问题。

更新(全部在bash 4.2.45(2),Mac OS 10.9下完成)

测试

当我尝试直接从bash执行命令时。我的意思是for循环。有一些有趣的东西。我首先使用:

将所有名称存储到 files.txt 文件中
$ ls | grep mp3 > files.txt

做sed和bla bla。而在bash交互模式下的单个命令如:

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

给出

第01课.mp3

在以下交互模式中:

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

没有变化!

到现在为止:

echo $file

给出:

$ 제30과.mp3

(只有30个文件)

问题部分

我尝试了之前有效的第一个命令:

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

它没有改变:

$ 제30과.mp3

所以我创建了一个新的 newfile 并再次尝试:

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

它正确地给出了:

$第30课.mp3

WOW ORZ ......为什么!为什么!为什么!我试着看看 file newfile 是否相同,当然,它们不是:

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

给出:

False

我的猜测

我猜有一些编码问题,但我发现没有参考,有人可以帮忙吗?再一次。

更新2

我似乎明白字符串和文件名之间存在巨大差异。具体来说,我直接使用如下变量:

file="제30과.mp3"
脚本中的

sed工作正常。但是,如果变量是从$ @传递的,或者将变量设置为:

file=./*mp3

然后sed无效。我不知道为什么。顺便说一下,mac sed没有-r选项,在ubuntu -r中没有解决我上面提到的问题。

2 个答案:

答案 0 :(得分:1)

结合了一些错误:

  • 要在正则表达式中使用组,您需要在sed中使用扩展的正则表达式-r,在grep中使用-E
  • 正确逃避是一头野兽:)

实施例

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

输出

第2课.mp3
第30课.mp3

答案 1 :(得分:0)

如果您不是作为编程项目执行此操作,但想要跳到它正常工作的部分,我发现这些资源列在http://www.tldp.org/LDP/GNU-Linux-Tools-Summary/html/x4055.htm

  • MMV(和MCP,MLN,...)实用程序使用专门的语法在路径上执行批量文件操作。 (http://linux.maruhn.com/sec/mmv.html

    mmv before\*after.mp3 Before\#1After.mp3

  • Esomaniac,一种也适用于Windows的Java替代品,显然已经死了(主页已停放)。

  • 重命名是一个可以从CPAN下载的perl脚本:https://metacpan.org/release/File-Rename

    rename 's/\.JPG$/.jpg/' *.JPG