【问题标题】:Bash - dirname: missing operandBash - 目录名:缺少操作数
【发布时间】:2021-02-02 16:28:30
【问题描述】:

我的管道获取terragrunt.hcl 文件的目录并针对它运行一堆测试。如果我的 if 语句为真,我希望我的 bash 执行 2 个命令,如果不是真的跳转到 else 语句,我的 else 应该什么都不做并退出。 下面的这个 bash 确实有效,但是只要不触及terragrunt.hcl,我就会在管道日志中得到这个错误。我假设我的 if 声明中的某些内容!

这是我的狂欢:

#!/bin/bash

if find . -name "terragrunt.hcl" -print0 | xargs -0 git diff-tree --no-commit-id --name-only -r $CI_COMMIT_SHA ; then # output only latest terragrunt.hcl commit
   find . -name "terragrunt.hcl" -print0 | xargs -0 git diff-tree --no-commit-id --name-only -r $CI_COMMIT_SHA | xargs -n 1 dirname | uniq # command 1
   for i in $(find . -name "terragrunt.hcl" -print0 | xargs -0 git diff-tree --no-commit-id --name-only -r $CI_COMMIT_SHA | xargs -n 1 dirname | uniq); do cd /usr/bin/regula/bin && ./regula /path/to/$i /usr/bin/regula/lib /path/to/custom-rules; done # command 2
else 
   :
fi

这是错误:

$ ./compliance_check.sh
dirname: missing operand
Try 'dirname --help' for more information.
dirname: missing operand
Try 'dirname --help' for more information.
Cleaning up file based variables
00:01
Job succeeded

请帮忙!!!

【问题讨论】:

  • 顺便说一句,考虑将您的cd 限定为子shell。 f/e,这可能看起来像 (cd /usr/bin/regula/bin && exec ./regula /path/to/"$i" /usr/bin/regula/lib /path/to/custom-rules) - exec 使用由 ( 创建的子shell,因此不会影响性能,而且您在子shell 中完成了 cd 的事实意味着它不会t 更改脚本其余部分所在的目录。
  • 另外,for i in $(anything) 是错误的形式;见BashPitfalls #1。请参阅Using Find 的“操作”和“复杂操作”部分。并且您可以存储第一个 find 的输出,因此您无需在 if 块内重新运行它。乍一看,似乎还有额外的空间可以避免重复工作。
  • ...或者,如果您存在该名称下只有一个文件,那么处理该期望被明确打破的情况可能会更好;这样,经过处理程序的代码可以确保假设是正确的。

标签: bash gitlab-ci


【解决方案1】:

如果您不希望 xargs 使用空参数列表运行 dirname,并且它是 GNU 版本,那么就这样做吧:

xargs --no-run-if-empty -n 1 dirname

...对于那个管道元素。

(另外,考虑使用-d $'\n' 来抑制xargs 在不使用-0 时开箱即用的一些更不幸的行为。


减少重复工作的替代实现可能看起来有点像以下代码(完全未经测试,因为该问题使用了其他人无法访问/测试的工具和目录结构):

#!/usr/bin/env bash
case $BASH_VERSION in ''|[0-3].*) echo "ERROR: Bash 4.0+ required" >&2; exit 1;; esac

declare -A dirnames=( )
readarray -d '' -t targetFiles < <(find . -name "terragrunt.hcl" -print0)
for file in "${targetFiles[@]}"; do
  readarray -t changedFileNames < <(
    git diff-tree --no-commit-id --name-only -r "$CI_COMMIT_SHA" "$file"
  )
  for changedFileName in "${changedFileNames[@]}"; do
    dirnames[${changedFileName%/*}]=1
  done
done
for dirname in "${!dirnames[@]}"; do
  (cd /usr/bin/regula/bin && exec ./regula /path/to/"$dirname" /usr/bin/regula/lib /path/to/custom-rules)
done

【讨论】:

  • xargs --no-run-if-empty -n 1 dirname 是缺少的和平。在我将那部分注入 bash 之后,错误就消失了:)...是的,我完全同意有很多不同的方法可以使这个更干净:)。我记下了所有的指针!!祝福所有最有帮助的人!!!!
猜你喜欢
  • 1970-01-01
  • 2018-11-16
  • 2011-10-22
  • 1970-01-01
  • 1970-01-01
  • 2013-12-17
  • 2023-02-22
  • 2017-06-16
  • 1970-01-01
相关资源
最近更新 更多