【问题标题】:Bash loop command on list列表中的 Bash 循环命令
【发布时间】:2012-02-19 19:34:10
【问题描述】:

我在 OS X 上使用 bash 并希望读取 Applications 目录中每个 Application 中嵌入的密钥中的数据。结果似乎是“默认”命令试图将自身应用于整个列表而不是每个返回的应用程序。

#!/bin/bash

# appList=$(ls /Applications)

for APPS in "$( ls /Applications )" ; do
        result=$(defaults read /Applications/"$APPS"/Contents/Info DTPlatformBuild)
done

echo result is $result

exit 0

任何帮助表示赞赏。

【问题讨论】:

    标签: macos bash loops for-loop


    【解决方案1】:

    "$( ls /Applications )" 之类的内容周围加上引号会导致shell 将引用的内容视为单个参数,而不是在空格处将其拆分为多个参数。所以你的for 循环只会执行一次,APPS 设置为整个应用程序列表,而不是为每个应用程序运行一次。如果您删除引号,它将为每个应用程序运行一次,只要应用程序的名称中没有任何空格。不幸的是,如果名称中有空格,它将破坏空格处的名称并且无法正常工作。

    安全地处理带有空格的文件名对 shell 来说是一件痛苦的事,这就是为什么建议您不要在文件名中使用空格的原因。不幸的是,微软和苹果没有遵循这个建议。在这种情况下,您可以做的一件事是:

    ls /Applications | while read APPS; do
        result=...whatever
    done
    

    您的脚本(如所写)的另一个问题是它会在每次迭代中存储到结果中,并覆盖之前的结果。因此,您打印的最后$result 的内容将只是最后一次迭代的结果。

    【讨论】:

    • 感谢您的 cmets @Chris,因为您让我清楚地知道我哪里出错了,这很有意义。我同意使用空格并告诉我们的办公室用户不要在文件名中使用它们。
    【解决方案2】:

    我建议不要使用ls 命令进行循环,因为它容易出错。像这样运行循环以递归方式查找应用程序:

    find /Applications -name "*.app" -print0 | while IFS= read -r -d '' APP
    do
        defaults read "$APP/Contents/Info" DTPlatformBuild
    done
    

    由于您对回显结果感兴趣,因此无需将默认命令的输出存储在变量中然后回显它。

    【讨论】:

    • 感谢@anubhava,这确实有效,但我也需要浏览子目录并满足不存在密钥的地方。我很想知道为什么ls 容易出错,谢谢。
    • 请阅读有关解析 ls 输出的信息:mywiki.wooledge.org/ParsingLs 您可以在 SO 上找到许多 Q&A 以及讨论在循环中使用 ls。如果您想要递归应用程序,请查看我更新的答案。
    • 感谢@anubhava 我已经阅读并学会了不使用ls,我修改了我的代码以使其与您的答案相符。
    【解决方案3】:

    我将使用以下内容。文本文件“appleApps.txt”只是新版本中默认 Apple 应用程序的列表,以弃权搜索。 一个有效的公司应用程序会在“Info.plist”文件中插入一个新的key,并将boolean设置为true
    因此,我们现在有一种机制来报告用户是否正在安装他们自己的应用程序副本,我们已经自己打包了。

    #!/bin/bash
    echo " "
    echo " "
    rm -f /tmp/validApps /tmp/notValid
    find /Applications -name "*.app" | grep -v -F -f /Library/Application\ Support/CompanyData/appleApps.txt | while read APP
    do
    appVersion=`defaults read "$APP/Contents/Info" Company 2>/dev/null`
    if test "$appVersion" = 1 ; then
        echo "$APP : $appVersion" >> /tmp/validApps
    else
        echo "$APP" >> /tmp/notValid
    fi
    done
    
    echo " "
    echo " "
    
    result=$(cat -n /tmp/validApps)
    notValidResult=$(cat -n /tmp/notValid)
    
    printf "%s\n" "Our packaged Applications are:" "$result"
    echo " "
    echo " "
    printf "%s\n" "User installed Applications are:" "$notValidResult"
    echo " "
    
    rm -f /tmp/validApps /tmp/notValid
    
    exit 0
    

    感谢我在$result 中的错误提示

    按照@chris 和@anubhava 的提示,我了解了为什么不向我们发送ls 并学会了不这样做

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-09-29
      • 2016-07-27
      • 1970-01-01
      • 2012-10-16
      • 1970-01-01
      • 2014-01-20
      相关资源
      最近更新 更多