2013-10-27 26 views
1

问题:脚本将接收任意数量的文件名作为参数。脚本应检查提供的每个参数是否是文件或目录。如果目录报告。如果文件,那么文件的名称加上存在的行数应该被报告。shell用户变量的差异

下面是我的代码,

#!/bin/sh 
for i in $*; do 
    if [ -f $i ] ; then 
     c=`wc -l $i` 
     echo $i is a file and has $c line\(s\). 
    elif [ -d $i ] ; then 
    echo $i is a directory. 
    fi 
done 

输出:

[email protected]:~/unixstuff/shells$ ./s317i file1 file2 s317h s317idir 
file1 is a file and has 1 file1 line(s). 
file2 is a file and has 2 file2 line(s). 
s317h is a file and has 14 s317h line(s). 

我的问题:变量c的值是1文件1,2文件2,在每个迭代上14 s317h。而我想要它到1,2和14.为什么它包含前值而不是后者?我错在哪里?

注意:s317i是我的文件名,file1 file2 s317h和s317idir是命令行参数。

请指教。

+2

“为什么它包含以前的值” - 只要在控制台上输入'wc -l some_file',你就会明白为什么。我怀疑这不是你想问的问题。 – Mat

+0

尝试'c = \'cat $ i | wc -l \''这样wc就没有要打印的文件名了。 –

回答

3

这是wc命令的输出。例如:

$ wc -l file1 
1 file1 

但是如果从file1或管道重定向stdin另一个命令的stdoutwc那么它不会给你的文件名。

$ wc -l < file1 
1 
$ cat file1 | wc -l 
1 

因此你的脚本应如下:

#!/bin/bash 

for arg in [email protected]; do 
    if [ -f $arg ]; then 
     echo $arg is a file and has `wc -l < $arg` lines. 
    elif [ -d $arg ]; then 
     echo $arg is not a file, it is a directory. 
    fi 
done 

请注意,我使用bash代替sh[email protected]而不是$*

+2

只是一件小事:如果你使用“测试”外部或他的叉子“[”而不是“[[”内部KSH/Bash指令,你必须用双打引号保护你的变量。 请参阅http://stackoverflow.com/a/19598570/2900196以获取更多详细信息。 –