LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 3341|回复: 15

如何批量去掉文件名中的空格[已解决]

[复制链接]
发表于 2004-2-5 17:48:23 | 显示全部楼层 |阅读模式
设一个目录下有很多文件名含有空格的文件
现在想要把这些空格都去掉并重命名,先看看下面的一个教本<delblank.sh>:
#!/bin/bash
ls > ls.tmp
while read Line
do
   file=`echo $Line | sed -e 's/ /\\ /g'`
   newfile=`echo $Line | sed -e 's/ //g'`
   if [ "$file" != "$newfile" ] ; then
      mv "$file" "$newfile"
   else
      continue
   fi
done < ls.tmp
rm -f ls.tmp
exit 0
上面的Shell程序基本可以满足要求,如
目录下原来有文件: shell use guide , i love linux
则执行sh delblank.sh后,文件名变为: shelluseguide , ilovelinux
但是当文件名中含有连续的空格时,在移动文件时就会出错。

How to solve this problem, and may be you have another better script. Just waiting for your 指点......
发表于 2004-2-5 18:09:26 | 显示全部楼层
  1. ls|while read i;do
  2.         mv "$i" $(echo $i|tr -d ' ') 2>/dev/null
  3. done
复制代码
 楼主| 发表于 2004-2-5 20:43:46 | 显示全部楼层
Thanks very much !
发表于 2004-2-16 19:06:28 | 显示全部楼层
for file in *; do mv "$file" "${file// /}"; done 2> /dev/null
发表于 2004-3-18 10:54:29 | 显示全部楼层
最初由 javalee 发表

  1. ls|while read i;do
  2.         mv "$i" $(echo $i|tr -d ' ') 2>/dev/null
  3. done
复制代码



奇怪为啥for的in和while的read会差这么多?


  1. root -> [test]# for i in `ls`;do echo "$i";done
  2. test
  3. 1
  4. test
  5. 2
  6. test
  7. 3
  8. test
  9. 4
  10. root -> [test]# ls|while read i;do echo "$i";done
  11. test 1
  12. test 2
  13. test 3
  14. test 4
复制代码


而用*又正常...


  1. root -> [test]# for i in *;do echo "$i";done
  2. test 1
  3. test 2
  4. test 3
  5. test 4
复制代码


:confused:
发表于 2004-3-19 20:20:12 | 显示全部楼层

while read i;do echo $i;done的原理其实就是下列的"批处理":
  1. exec 3< file #文件描述符3打开文件
  2. read -u3 var1 #读取第一行
  3. echo $var1    #并显示
  4. read -u3 var2
  5. echo $var2
  6. ...
  7. read -u3 varN #读取第N行
  8. echo $varN    #并显示
  9. exec 3<&-      #关闭文件描述符3,即关闭文件
复制代码

可以这么说,while的read是逐行读取变量的空格是被忽略的,而行的结束符号是什么? --换行符/回车符
而for是逐个读取的变量列表中的变量的,变量的赋值方式又是以空格或回车为分隔域的,由此看出用for和while的区别~
发表于 2004-3-20 01:53:40 | 显示全部楼层
那for i in *又怎么解释呢?

root -> [test]# for i in *;do echo "$i";done
test 1
test 2
test 3
test 4


这个又正常.
发表于 2004-3-20 02:24:22 | 显示全部楼层
原因出在IFS身上!
系统默认的IFS变量:
/home/javalee/abc/test:set|grep -A1 IFS
IFS='
'
/home/javalee/abc/test:
/home/javalee/abc/test:for i in `ls`;do echo $i;done
c
test
1
test
2
我们修改他 ;)在看看结果
/home/javalee/abc/test:IFS=
/home/javalee/abc/test:set|grep IFS
IFS=
_=IFS
/home/javalee/abc/test:
/home/javalee/abc/test:for i in `ls`;do echo $i;done
c
test 1
test 2
/home/javalee/abc/test:
再改回来 ;)
/home/javalee/abc/test:IFS='    #这里单引号后面有关空格
=>'
/home/javalee/abc/test:for i in `ls`;do echo $i;done
c
test
1
test
2
IFS的解释:
内部分隔符,一般是空格,tab符和换行符,用于域划分命令产生的词

`ls`是由于命令产生的输出,*号是个shell同配符,即所有文件!他们的区别应该很明显的吧~~
我的解释也许不是很好,更好的解释可以看看置顶里面的教程吧~
发表于 2004-3-20 03:18:17 | 显示全部楼层
javalee兄, 我试了你的script后不成功, 输出为:
[root@localhost shell_scripts]# ls
aa  dir1  dir2  dir3  test 1  test 2  test 3
[root@localhost shell_scripts]# ls | while read i; do mv $i $(echo $i|tr -d ' '); done
mv: `aa' and `aa' are the same file
mv: cannot move `dir1' to a subdirectory of itself, `dir1/dir1'
mv: cannot move `dir2' to a subdirectory of itself, `dir2/dir2'
mv: cannot move `dir3' to a subdirectory of itself, `dir3/dir3'
mv: when moving multiple files, last argument must be a directory
Try `mv --help' for more information.
mv: when moving multiple files, last argument must be a directory
Try `mv --help' for more information.
mv: when moving multiple files, last argument must be a directory
Try `mv --help' for more information.
[root@localhost shell_scripts]# ls
aa  dir1  dir2  dir3  test 1  test 2  test 3

是什么原因呢? 我在另台机上试, 还出现了"mv: cannot stat `\033[00;34m.\033[00m/` 的奇怪报错. dearvold 兄的script也很简捷, 用pattern更换就把问题解决了.  目录结构如上所示, 有dir, 有空格文件名, 有正常文件名.
发表于 2004-3-20 10:37:30 | 显示全部楼层
加一个判断:
  1. ls|while read i;do
  2. echo $i|grep -q " "&& mv "$i" "$(echo $i|tr -d ' ')";done
复制代码
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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