LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
12
返回列表 发新帖
楼主: NeoAnderson

[脚本] 规范化文件名

[复制链接]
 楼主| 发表于 2005-1-20 22:54:10 | 显示全部楼层
都没用。
对,我要改的是文件名
回复 支持 反对

使用道具 举报

发表于 2005-1-20 23:13:34 | 显示全部楼层
刚发现我用rename是用perl写的一个脚本,
那就没意思了, 还不如自己写呢,
下面是我尝试写的一个: (还没测试)

  1. #!/bin/sh
  2. for file in *
  3. do
  4. newname=`echo $file|sed 's/[_\ ]/-/g'`
  5. echo $newname
  6. newname2=`echo $newname|sed 's/--*/-/g'`
  7. echo $newname2
  8. newname3=`echo $newname2|sed 's/\(^[a-z]\{1\}\)/\U\1/'`
  9. echo $newname3
  10. #mv "$file" "$newname3"
  11. done
复制代码
回复 支持 反对

使用道具 举报

 楼主| 发表于 2005-1-21 09:30:35 | 显示全部楼层
我用DSL的方法重写了,内容大大缩减但好像有点问题。中括号的问题还是存在。请各位帮看看

  1. #!/bin/bash

  2. # This script turns underlines and blanks in filenames to hyphens
  3. # Written by Neo Anderson <ZeeGeek@gmail.com>
  4. # Jan 19 2005

  5. DIR=$1
  6. TEMP_FILE="/tmp/ulb2h.tmp"

  7. ulbtoh() {
  8.         exec < $TEMP_FILE
  9.         while read FILE_NAME
  10.         do
  11.                 BASE_NAME="`basename "$FILE_NAME"`"
  12.                 FINAL_NAME="${FILE_NAME%$BASE_NAME}$(echo "$BASE_NAME" | tr -s ' |_' '-')"
  13.                 # rename target
  14.                 mv "$FILE_NAME" "$FINAL_NAME"
  15.                 sleep 3
  16.         done
  17.         rm $TEMP_FILE
  18. }

  19. usage() {
  20.         echo "Usage: ul2h.sh [directory...]"
  21. }

  22. if [ -z $DIR ]
  23. then
  24.         usage
  25. else
  26.         # get the file list of filenames containing underlines or blanks
  27.         find $DIR -type f -iname '*_*' > $TEMP_FILE
  28.         find $DIR -type f -iname '* *' >> $TEMP_FILE
  29.         ulbtoh
  30.         # get the file list of directory names containing underlines
  31.         find $DIR -iname '*_*' > $TEMP_FILE
  32.         find $DIR -iname '* *' >> $TEMP_FILE
  33.         ulbtoh
  34. fi
复制代码
    
回复 支持 反对

使用道具 举报

发表于 2005-1-21 12:17:07 | 显示全部楼层
可以用以下语句将' '_-(多个)都改为一个-
echo $name | sed 's/[_\ -]\+/-/g'
用 's/^[a-z]/\U&/' 可以把头字母大写

我觉得用判断改后和改前是否有差别可以缩短长度
if [ "$newname" != "$name" ]
then
...
fi
回复 支持 反对

使用道具 举报

 楼主| 发表于 2005-1-21 13:17:06 | 显示全部楼层
我是想将每个单词的首字母大写,不仅仅是文件名的首字母。
我的思路是这样的:
1、获取给定文件夹下所有需要改的文件名,并将这些文件名存到临时文件;
2、开始更改,改完整个列表的文件名后将临时文件删掉;
3、获取给定文件夹下所有需要更改的目录名,并存到临时文件;
4、开始更改,改完删掉临时文件。
因为我是一次获得文件列表之后就根据文件列表进行更改,所以不能先更改目录名,否则后面出现该目录下的文件就会找不到了。改完文件名再改目录名就没问题。例如,文件列表有以下内容:
/abc/t__est/
/abc/t__est/f_i_l_e
如果先更改了目录t__est的话,到改f_i_l_e文件时由于目录已经不存在而无法更改。
我不太明白lastart所说的用判断具体怎么实现,请稍微讲解一下,谢谢
回复 支持 反对

使用道具 举报

发表于 2005-1-21 20:44:19 | 显示全部楼层
我的意思是不管文件是否合规范都改了.改后比较是不是跟原来的是一样的. 如果是则不处理.
其实如果用find你可以把文件倒序了, 就不会出现先改目录的问题.
下面是我写的一个, 用了vim, 有点赖皮了.呵呵
不过应该比较合你的要求吧

  1. #!/bin/sh
  2. echo -n > /tmp/orgfile
  3. find "$1" >>/tmp/orgfile
  4. tac /tmp/orgfile >/tmp/revfile
  5. vim -c "%s/.*\//" -c "%s/[-_\ ]\+/-/g" -c "%s/\<.\{-}\>/\u&/g" -c "%s/\<A\>/a/g" -c "%s/\<\cof\>/of/g" -c "%s/\<\cthe\>/the/g" -c "wq! /tmp/tempfile" /tmp/revfile
  6. #cd "$1"
  7. i=$((1))
  8. while read oldname
  9. do
  10.         mv "$oldname"  "`dirname "$oldname"`/`cat /tmp/tempfile|sed -n "$i,$i"p`"
  11.         i=$(($i+1))
  12. done < /tmp/revfile
  13. rm -f /tmp/orgfile /tmp/revfile /tmp/tempfile
复制代码

运行效果大概是这样的, 测试的时候我把mv 改为echo了. 我这里没有加上文件名是否相同的判断.所以都改了.
不过源名和目标名相同mv会自动不执行.所以也没什么问题.

  1. ./.swp --> ./.Swp
  2. ./a -b__-c[d -c]/dks_-fjkd 0- --> ./a -b__-c[d -c]/Dks-Fjkd-0-
  3. ./a -b__-c[d -c]/a_b-d[/dks_-fjkd 0- --> ./a -b__-c[d -c]/a_b-d[/Dks-Fjkd-0-
  4. ./a -b__-c[d -c]/a_b-d[ --> ./a -b__-c[d -c]/a-B-D[
  5. ./a -b__-c[d -c] --> ./a-B-C[D-C]
  6. ./rename --> ./Rename
  7. ./.tmp.swp --> ./.Tmp.Swp
  8. ./test --> ./Test
  9. ./tmp --> ./Tmp
  10. ./dks_-fjkd 0- --> ./Dks-Fjkd-0-
  11. ./.test.swp --> ./.Test.Swp
  12. ./ --> ./
复制代码

真正运行之后的效果如下

  1. lastart@qf-host:/tmp/test$ find .
  2. .
  3. ./test
  4. ./.Test.Swp
  5. ./Tmp
  6. ./Test
  7. ./.Tmp.Swp
  8. ./Rename
  9. ./Dks-Fjkd-0-
  10. ./.Swp
  11. ./a-B-C[D-C]
  12. ./a-B-C[D-C]/a-B-D[
  13. ./a-B-C[D-C]/a-B-D[/Dks-Fjkd-0-
  14. ./a-B-C[D-C]/Dks-Fjkd-0-
复制代码
回复 支持 反对

使用道具 举报

 楼主| 发表于 2005-1-22 00:42:49 | 显示全部楼层
佩服佩服,真是利害,所有功能都实现了。非常感谢!这篇贴子学了不少。我得好好看看vim后面那串东西。
回复 支持 反对

使用道具 举报

发表于 2005-1-22 01:05:03 | 显示全部楼层
感觉sed的某些代替没用vim好用.
化简一下

  1. #!/bin/sh
  2. find "$1" | tac | while read oldname
  3. do
  4.     newname="`dirname "$oldname"`/`basename "$oldname"|sed "s/[-\ _]\+/-/g"|sed "s/-[A-Za-z]\|^[A-Za-z]/\U&/g"|sed "s/\<Of\|A\|The\|For\|With\>/\L&/g"`"
  5.     if [ "$2" = "do" ]
  6.     then
  7.         mv "$oldname" "$newname"
  8.     fi
  9.     echo "$oldname" '-->' "$newname"
  10. done
复制代码

使用:
程序 目录 [do]
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表