检查bash中目录的可读文件

时间:2014-07-28 04:58:29

标签: bash for-loop ls

我是Bash脚本的新手,我一直在玩它,但我有这个我不明白的脚本:

#!/bin/bash
for name in $(ls $HOME)
do
    if [ -f $name -a -r $name ]
    then
        echo "$name is file"
    fi
done

如果我运行它,它什么都不打印。 我很确定在我的主目录中我有可读文件。例如:

-rw-r--r--  1 user user        368 feb 17 22:39 requirements.txt

如果我用另一个目录测试它,它告诉我有两个可读的文件:

-rwxr-xr-x 1 user user  442 jul 27 23:47 longest-and-shortest-username.sh
-rwxr-xr-x 1 user user 1155 jul 28 00:39 options-for-files-in-directory.sh

My Bash版本是:4.2.45(1)-release

我失去了什么吗?

2 个答案:

答案 0 :(得分:3)

代码试图获取HOME目录中的文件名。但是,它正在测试当前目录中是否存在该名称(必须是不同的)。

解决方案是将目录附加到文件名。尝试:

for name in "$HOME"/*
do
    if [ -f "$name" -a -r "$name" ]
    then
        echo "$name is file"
    fi
done

上面的另一个优点是它适用于带空格的文件名和其他敌对角色的所有庄园。

bash看到$(ls $HOME)时,它会运行ls $HOME,然后对结果应用分词。因此,如果您有一个名为my file的文件,bash会将其分为两个参数myfile。你不想要这个。相比之下,当bash看到$HOME/*时,它会返回所有未受损的文件名。

另请注意,我在$name的{​​{1}}附近加了双引号。这可以防止分词,并确保此测试适用于所有文件名。

答案 1 :(得分:0)

最好的方法是调试脚本,以便识别问题:

#!/bin/bash
echo "Current directory is $PWD."
echo "HOME is $HOME."
for name in $(ls $HOME)
do
    echo "Checking $file."
    if [ -f $name -a -r $name ]
    then
        echo "$name is file"
    fi
done

以下是一些提示,但在发现问题原因之前,请不要修改脚本。

  • 将打开的变量括在双引号对中,以防止分词和路径名扩展。
  • 首选[[ ]]优先于[ ],因为它不进行分词和 路径名扩展。
  • 可能没有必要使用ls。您可以使用"$HOME"/*
  • 如果需要ls,请考虑使用while read循环代替进程:while IFS= read -r file; do ...; done < <(exec ls -1 "$HOOME"),因为它会阻止字拆分和路径名扩展。并使用-1选项。