Shell识别文件〜但不在〜/ Documents中

时间:2014-11-28 17:30:05

标签: linux bash shell

我参加了一个Unix课程,这是我的任务的一部分:

对于用户的〜/ Documents目录中的每个文件和子目录,确定该项是文件还是目录,并使用语句中的文件名显示相应的消息。

所以,我写的是:

docs=`ls ~/Documents`

for file in $docs ; do
    if [ -f $file ] ; then
        echo $file "is a file."
    elif [ -d $file ] ; then
        echo $file "is a directory."
    else
        echo $file "is not a file or directory."
    fi
done

我的文档目录包含以下文件和目录:

DocList.txt  (file)
Letter       (file)
mypasswdfile (file)
samples      (directory)
things       (directory)
touchfile    (file)

所以我认为输出应该是这样的:

DocList.txt is a file.
Letter is a file.
mypasswdfile is a file.
samples is a directory.
things is a directory.
touchfile is a file.

然而,这是输出:

DocList.txt is not a file or directory.
Letter is not a file or directory
mypasswdfile is not a file or directory
samples is not a file or directory
things is not a file or directory
touchfile is not a file or directory

如果我将$ docs变量设置为`ls~'它将成功显示我的主目录的内容以及这些项目是文件还是目录。这不适用于我尝试的其他路径。

2 个答案:

答案 0 :(得分:2)

问题在于您的ls命令 - 您将ls的输出视为绝对值,例如/home/alex/Documents/DocList.txt,但当您执行ls ~/Documents时,它会打印出DocList.txt(相对文件路径/名称)。

要获得预期的绝对行为,您可以改为使用find命令:

docs=`find ~/Documents`

正如评论和其他答案中所提到的,为了能够处理文件名中的空格,您需要执行以下操作:

docs=( ~/Documents/* )
for f in "${docs[@]}"; do
    ...

答案 1 :(得分:2)

您的问题是ls仅输出没有路径的文件名。

因此,您的$file获取值

DocList.txt
Letter
mypasswdfile
samples
things
touchfile

从循环运行到循环运行。

如果您当前的目录不是~/Documents,那么测试这些文件名是错误的,因为这会搜索当前目录而不是目标目录。

完成任务的更好方法是

for file in ~/Documents/* ; do
    ...
done

$file设置为查找文件所需的每个完整路径名。

这样做之后,它应该可以工作,但它非常容易出错:一旦你的路径或其中一个文件开始有空格或其他空白字符,它就会落在你的脚上。

"放在可能包含空格等的变量周围是非常必要的。几乎没有理由在没有周围"的情况下使用变量。

这有什么区别?

使用[ -f $file ]file='something with spaces',使用参数[-fsomethingwith调用spaces]。这肯定会导致错误的行为。

使用参数[ -f "$file" ]file='something with spaces'[调用带有-fsomething with spaces]的OTOH。

所以引用在shell编程中非常重要。

当然,同样适用于[ -d "$file" ]