24

我对 bash 脚本还很陌生,所以这可能是一个愚蠢的语法错误,但为什么这段代码不起作用?

for x in $(ls)
do
  if [ -d $x ]
  then
  echo $x
  fi
done

单独的 for 和 if 部分可以自己正常工作,但这不会产生任何输出。

4

4 回答 4

31

两件事情。永远不要使用ls迭代文件和引用参数扩展"$x"。for 和 if 语法本身是正确的。我更喜欢把doandthen放在同一行

for file in *; do
    if [[ -d "$file" ]]; then
        echo "$file is a directory"
    elif [[ -f "$file" ]]; then
        echo "$file is a regular file"
    fi
done

对于学习 bash,我建议阅读http://mywiki.wooledge.org/BashGuide大多数其他教程和指南很遗憾不是很好。

不做for x in $(ls)迭代文件的原因是因为for迭代单词ls输出带有文件名的行。如果这些文件名恰好包含空格,则这些文件名将进一步拆分为单词,因此您将迭代文件名的单词,而不是文件名。显然,对于有效的简单案例,但是当有一种更短、更优雅的方式来处理所有案例时,为什么要使用半有效的解决方案呢?

使用for x in *shell 将 替换为*当前目录中与该模式匹配的所有文件名(称为路径名扩展),并且每个文件名将是一个单独的单词,因此无论文件名包含什么字符,它都会起作用。文件名可以包含任何字符(包括换行符),但/NUL 字节 (\0) 除外。

有关更多信息,请参阅http://mywiki.wooledge.org/ParsingLs

至于使用[[vs [[是继承自 bourne shell 的命令,用于测试字符串、文件和数字。Bash 添加了一个更强大的[[关键字,可以做任何事情[,甚至更多。如果你正在编写一个 sh 脚本,你必须使用[,但是在 bash 脚本中你应该使用更强大的[[((语法。有关和之间区别的更多信息,请参阅http://mywiki.wooledge.org/BashFAQ/031[[[

于 2012-08-19T21:57:13.523 回答
6

也许用于分隔语句不同部分的字符存在问题?

如果您尝试过:

for x in $(ls); do if [ -d $x ]; then echo $x; fi; done

这会产生输出吗?

于 2012-08-19T21:58:20.867 回答
1

1) 语法完全合法

2) 是的,您可以在循环内嵌套“if/else”块。您还可以在外循环中嵌套内循环:)

3) "if [ -d $x ]" 检查"x" 是否是一个"目录"。

如果您没有看到任何输出,那么也许您没有任何子目录?

建议:

  • 打开终端窗口

  • 运行你的脚本。看看你是否得到任何输出。

  • 如果没有,则键入mkdir moose. 这将创建一个名为(意外地)“moose”的子目录。

  • 重新运行您的脚本。您至少应该看到“驼鹿”。

于 2012-08-19T21:56:18.833 回答
-2
#!/bin/bash

name=c
for command in "cd $home" " cd XSStrike" "python xsstrike.py"
do
    if [[ $name == "c" ]]; 
    then
        echo "<==========> access granted <==========>"
        $command
    else
        echo "<==========> access denied <==========>"
    fi
done
于 2019-06-20T08:10:03.013 回答