【问题标题】:control the sorting in for loop BASH控制 for 循环 BASH 中的排序
【发布时间】:2022-01-19 16:46:08
【问题描述】:

有什么方法可以控制我运行 a, for d in * 时发生的排序;做;回声 $i;完毕;在我的目录中?我有这个文件夹结构:

root/
  |__CloudUtils/
  |__ComponentSplit/
  |__ComponentStatistics/
  |__ETLManager/
  |__MergeComponent/
  |__NormalizeComponent/
  |__Reducer/

我想更改顺序,以便 mvn 将在 CloudUtils 之后立即编译 NormalizeComponent。

for d in */ ; do
    d=${d::-1}
    mvn clean deploy -f "$d"
done

有办法吗?

【问题讨论】:

  • 你想要的排序顺序的逻辑是什么?如果您只想先处理特定文件,请不要在循环中进行。
  • 如果您在${d::-1} 中的目标是从末尾剥离/,则使用${d%/} 对读者来说更明确地说明了该意图(并且具有不会剥离的额外好处任何不是 /)
  • 给定这个目录结构,这难道不是for d in root/*cd root; for d in * 而不是您发布的代码吗?在这两种情况下,文件名的生成都应该在 bash 下按字母顺序完成。
  • 对于更复杂的依赖关系,使用 Makefile 不是更干净的方式吗?

标签: bash shell


【解决方案1】:

Charles 答案的变体:

shopt -s extglob
exception='NormalizeComponent'
dirs=( !("$exception")/ )
dirs=( "${dirs[0]}" "$exception"/ "${dirs[@]:1}" )
for d in "${dirs[@]}"; do
  echo "$d"
done

输出

CloudUtils/
NormalizeComponent/
ComponentSplit/
ComponentStatistics/
ETLManager/
MergeComponent/
Reducer/

【讨论】:

    【解决方案2】:

    只有在存在符合您需要的排序规则的情况下,您才能控制排序结果; LC_COLLATE 可用于选择要使用的顺序 - 但在这种情况下,您的操作系统提供的所有顺序都不会匹配您想要的行为。


    您可以使用 extglob with a negative assertion 将特定目录排除在 glob 的结果之外,这样您就可以对第一项和第二项进行硬编码,并按照语言环境的排序规则设置提供的顺序执行其他所有操作:

    #!/usr/bin/env bash
    [ -n "$BASH_VERSION" ] || { echo "ERROR: only bash is supported" >&2; exit 1; }
    
    shopt -s extglob
    for d in CloudUtils NormalizeComponent !(CloudUtils|NormalizeComponent)/; do
        mvn clean deploy -f "${d%/}"
    done
    

    【讨论】:

      猜你喜欢
      • 2022-01-07
      • 2014-08-06
      • 1970-01-01
      • 1970-01-01
      • 2020-08-23
      • 1970-01-01
      • 2013-05-25
      • 2013-12-16
      相关资源
      最近更新 更多