【问题标题】:Bourne Shell Scripting -- simple for loop syntaxBourne Shell 脚本——简单的 for 循环语法
【发布时间】:2010-12-19 12:43:29
【问题描述】:

我对编程并不完全陌生,但我并不完全有经验。我想写一个小shell脚本来练习。

这是我目前所拥有的:

#!/bin/sh
name=$0
links=$3
owner=$4
if [ $# -ne 1 ]
then
        echo "Usage: $0 <directory>"
        exit 1
fi
if [ ! -e $1 ]
then
        echo "$1 not found"
        exit 1

elif [ -d $1 ]
then
        echo "Name\t\tLinks\t\tOwner\t\tDate"
        echo "$name\t$links\t$owner\t$date"
        exit 0
fi

基本上我要做的是让脚本遍历指定目录中的所有文件,然后显示每个文件的名称以及它拥有的链接数量、它的所有者以及它的创建日期.显示创建日期或至少显示文件最后修改日期的语法是什么?

另一件事是,创建 for 循环的语法是什么?据我了解,我必须在 $1 中编写类似 for $1 的内容($1 是用户输入的目录中的所有文件是否正确?),然后检查每个文件并显示每个文件的信息。我将如何开始和结束 for 循环(这是什么语法?)。

如您所见,我对 bourne shell 编程不是很熟悉。如果您有任何有用的网站或有更好的解决方法,请告诉我!

【问题讨论】:

    标签: shell unix scripting terminal sh


    【解决方案1】:

    for 循环的语法:

    for var in list
    do
        echo $var
    done
    

    例如:

    for var in *
    do
        echo $var
    done
    

    但是,您可能要考虑的是这样的:

    ls -l | while read perms links owner group size date1 date2 time filename
    do
       echo $filename
    done
    

    它将ls -l 的输出即时拆分为字段,因此您无需自己进行任何拆分。

    字段分割由 shell 变量 IFS 控制,默认情况下包含空格、制表符和换行符。如果您在 shell 脚本中更改它,请记住将其更改回来。因此,通过更改 IFS 的值,您可以例如通过将其设置为逗号来解析 CSV 文件。此示例从 CSV 读取三个字段并仅吐出第二个和第三个字段(它实际上是 cut -d, -f2,3 inputfile.csv 的 shell 等效项)

    oldifs=$IFS
    IFS=","
    while read field1 field2 field3
    do 
        echo $field2 $field3
    done < inputfile.csv
    IFS=oldifs
    

    (注意:您不需要恢复 IFS,但我通常会确保在我完成后不会影响脚本中的进一步文本处理)。

    for 和 while 循环中的大量文档;只是谷歌它:-)

    【讨论】:

    • 你的 for 循环中有一个多余的(和有害的)美元符号。它应该是for var in *; do ... done,在var 之前没有$。
    • 啊,你是对的,while 循环会更有效。感谢您的建议和语法解释。
    • @ndim -- 很好,已修复。在过去的一个小时里,我刚刚摆脱了对 perl 的摆弄。我眼前浮现了标点符号... :-)
    【解决方案2】:

    $1 是第一个位置参数,所以$3 是第三个,$4 是第四个。它们与启动脚本的目录(或其文件)无关。如果你的脚本是使用这个启动的,例如:

    ./script.sh apple banana cherry date elderberry
    

    那么变量$1 将等于“apple”,依此类推。特殊参数$# 是位置参数的计数,在本例中为五个。

    脚本的名称包含在$0 和$* 和$@ 中,这些数组包含所有位置参数,这些参数的行为取决于它们是否出现在引号中。

    您可以使用子字符串样式的索引来引用位置参数:

    ${@:2:1}
    

    将使用上面的示例给出“香蕉”。并且:

    ${@: -1}
    

    或

    ${@:$#}
    

    会给出最后一个(“接骨木”)。请注意,在这种情况下,减号前的空格是必需的。

    【讨论】:

      【解决方案3】:

      您可能想查看Advanced Bash-Scripting Guide。它有一个解释循环的部分。

      【讨论】:

        【解决方案4】:

        我建议将find 与-printf "%P\t%n\t%u\t%t" 选项一起使用

        【讨论】:

          【解决方案5】:
          for x in "$@"; do
              echo "$x"
          done
          

          “$@”保护提供的文件名中的任何空格。显然,做你真正的工作来代替“echo $x”,这并没有做太多。但是 $@ 是命令行中提供给脚本的所有垃圾。

          而且,如果 $# 不等于 1,您的脚本也会退出,但您显然完全期望最多 4 个参数(因此您在脚本的早期部分引用了 $4)。

          【讨论】:

            【解决方案6】:

            假设你的系统上有 GNU find

            find /path -type f -printf "filename: %f | hardlinks: %n| owner: %u | time: %TH %Tb %TY\n"
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2011-08-03
              • 1970-01-01
              • 2018-05-16
              • 2022-05-17
              • 2015-12-03
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多