【问题标题】:Why can't I pass a directory as an argument to a for loop in bash?为什么我不能将目录作为参数传递给 bash 中的 for 循环?
【发布时间】:2013-03-23 16:25:32
【问题描述】:

我有一个简单的bash脚本simple.sh,如下:

#/usr/local/bin/bash
for i in $1
   do
       echo The current file is $i
   done

当我使用以下参数运行它时:

./simple.sh /home/test/*

它只会打印并列出目录中的第一个文件。

但是,如果我将 simple.sh 更改为:

#/usr/local/bin/bash
DIR=/home/test/*
for i in $DIR
   do
       echo The current file is $i
   done

它会正确打印出目录中的文件。有人可以帮助解释为什么传递的参数没有显示相同的结果吗?

【问题讨论】:

    标签: bash directory


    【解决方案1】:

    如果你取“$1”,它是第一个文件/目录,这是可能的! 你应该这样做:

    for i in "$@"
    do
      echo The current file is ${i}
    done
    

    如果你执行它:

    ./simple.sh *
    

    他们列出了实际字典的所有文件

    "$1" 是当前目录的第一个文件/目录的字母顺序,在 for 循环中,"i" 的值将是例如a1.sh 然后他们就会退出 for 循环! 如果你这样做:

    DIR=/home/<s.th.>/* 
    

    您将所有文件/目录的值保存在 DIR 中!

    【讨论】:

    • 这应该是"$@",因此它甚至适用于名称中带有空格的文件。
    • 对于"$i",消息中也会保留空白。一切都是关于细节:-)
    • 最后部分的解释略有不妥;模式扩展不会发生在参数分配的右侧。当 $DIR 被扩展时,如果它不是引号,模式也会被扩展(如在原始问题中)。使用echo "$DIR" 进行验证。
    【解决方案2】:

    如何手动列出文件而不是使用 *:

      #/usr/local/bin/bash
      for i in $(ls $1)
      do
          echo The current file is $i
      done
    

    然后输入

     ./simple.sh /home/test/
    

    【讨论】:

    • 如果目录中的任何文件名包含空格,这将不起作用。
    【解决方案3】:

    这是可移植的,没有无用的 ls 分支,并且运行时浪费的 CPU 周期最少:

    #!/bin/sh
    cd $1
    for i in *; do
       echo The current file is "$i"
    done
    

    ./simple.sh /home/test运行

    【讨论】:

    • “最少浪费的 CPU 周期”可能是 C 而不是 bash,tbh ;-)
    • 不;不考虑编译的碳足迹,呃,循环足迹:-)
    【解决方案4】:

    您的脚本没有接收“/home/test/*”作为参数; shell 将模式扩展为匹配的文件列表,并且您的 shell 接收多个参数,每个匹配文件一个。引用参数将起作用:

    ./simple.sh "/home/test/*"
    

    您对使用 DIR=/home/test/* 的更改符合您的预期,因为文件名生成不是在变量赋值的 RHS 上执行的。当您在 for 循环中未引用 $DIR 时,该模式已扩展为匹配文件列表。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-01-11
      • 1970-01-01
      • 2018-09-03
      • 2022-01-23
      • 1970-01-01
      • 1970-01-01
      • 2016-08-16
      相关资源
      最近更新 更多