Chinaunix

标题: 路径含空格问题求解 [打印本页]

作者: worc    时间: 2007-06-21 21:52
标题: 路径含空格问题求解
正在看各置顶贴,还未找到答案。但因为比较急,所以先把问题发在这。

假设输入下列代码
read a ; for i in $a ; do echo $i ; echo 2 ; done
当提示用户输入时,输入*
那么当然会将当前目录下的文件打印出来,假设当前目录下只有a1,a2,a3等3个文件,那么得到
*(用户输入)
a1
2
a2
2
a3
2
这没有问题。
假设当前目录为/path/to/foo,将用户输入改为/path/to/foo/*,那么得到
/path/to/foo/*(用户输入)
/path/to/foo/a1
2
/path/to/foo/a2
2
/path/to/foo/a3
2
也没问题。
假设当前目录为/path/to/f oo(注意那个空格),问题来了:
输入/path/to/f oo/*或者/path/to/f\ oo/*,都得到
...(用户输入)
/path/to/f
2
oo/*
2
显然是空格的问题。
于是修改代码为
read a ; for i in "$a" ; do echo $i ; echo 2 ; done
再次输入/path/to/f oo/*或者/path/to/f\ oo/*,都得到
...(用户输入)
/path/to/f oo/*
2
$a不再展开。可以理解,但是问题是如何求全?即又要展开、又要兼顾空格的可能性。

在最后一种情况下,即
read a ; for i in "$a" ; do echo $i ; echo 2 ; done
如果当前目录为/path/to/foo,不再含空格,用户输入*,将得到
*(用户输入)
a1 a2 a3
2
何解?如果我在前面讲的够清楚,这显然不是我的需求,因为$i似乎只取了一次值。如何修正?

问题概括:
需要$i历遍用户输入的所有文件(用户可能利用通配符指定文件,需要能自动被识别并展开),但要照顾到路径包含空格的可能性。

写的比较罗嗦,希望讲清楚了问题。
作者: doctorjxd    时间: 2007-06-21 22:30
输入
"/path/to/f oo/*"
作者: ly5066113    时间: 2007-06-22 10:02
try

  1. #!/usr/bin/sh
  2. read a
  3. b=`echo "$a" | sed 's/ /\\\\ /g'`
  4. eval ls -l $b | awk -F: '{print substr($2,4)}'
复制代码

作者: worc    时间: 2007-06-22 10:35
已经用
oldifs=$IFS
IFS=
......(在for那句话里不要带引号了)
IFS=$oldifs
的方式解决了问题。

但是仔细想想,空格是暂时没问题了,那些特殊字符呢?
我发现Linux对文件名可用的字符的要求似乎很松散,随便试了几个shell的元字符,居然都可以当作文件名用。
看来要求用户尽量用字母、数字、下划线、点作文件名,可以省下很多麻烦。

但从程序设计者的角度出发,是要求用户适应程序,还是尽量让程序适应各种用户,似乎是个很值得思考的命题,呵呵。
作者: hongyunqi    时间: 2007-06-24 21:42
解释一下
再次输入/path/to/f oo/*或者/path/to/f\ oo/*,都得到
...(用户输入)
/path/to/f oo/*
2
$a不再展开。可以理解,但是问题是如何求全?即又要展开、又要兼顾空格的可能性。

在最后一种情况下,即
read a ; for i in "$a" ; do echo $i ; echo 2 ; done
如果当前目录为/path/to/foo,不再含空格,用户输入*,将得到
*(用户输入)
a1 a2 a3
2
何解?如果我在前面讲的够清楚,这显然不是我的需求,因为$i似乎只取了一次值。如何修正?


在用read读入用户自己输入的参数的时候,IFS在其中起了很大的作用
当输入/path/to/f oo/* 的时候,shell会根据IFS的值先进行分割,而默认情况下IFS就是空格表格符号和回车了,所以这时read a实际上得到的是两个分开的参数。然后shell又会进行展开重组,因为是两个参数,即使shell碰到*,不能展开了。

而后你(worc)说用"IFS="这种方法解决了问题,也是这个道理,因为这是空格已经不是分隔符了。
test
  1. >pwd
  2. /u/hong
  3. >mkdir "f    oo" #three space
  4. >cd "f    oo"
  5. >touch file1 file2
  6. >read a ; for i in "$a" ; do echo $i ; echo 2 ; done
  7. /u/hong/f   oo/*
  8. /u/hong/f oo/*  #变成一个空格了
复制代码





欢迎光临 Chinaunix (http://bbs.chinaunix.net/) Powered by Discuz! X3.2