【问题标题】:Prevent "mv" command from raising error if no file matches the glob. eg" mv *.json /dir/如果没有文件与 glob 匹配,则防止“mv”命令引发错误。例如" mv *.json /dir/
【发布时间】:2020-12-19 13:54:39
【问题描述】:

我想将在 jenkins 作业中创建的所有 JSON 文件移动到不同的文件夹。

作业可能没有创建任何 json 文件。 在这种情况下, mv 命令会引发错误,因此该作业会失败。

如果找不到文件,如何防止 mv 命令引发错误?

【问题讨论】:

  • 您可能无法“防止” mv(1) 引发错误。您可以重定向它的 标准错误 以便看不到错误,或者 - 更好 - 您可以在调用 mv 之前检查。
  • 如果没有文件匹配 glob,mv“看到”文字 *.json 作为源文件,当然不存在......你唯一能做的就是重定向输出,所以你不会看到错误,但它发生了,所以它就在那里。
  • ...如果您在mv *.json target 中设置shopt -s nullglob,则目标将成为源。
  • 你试过什么?如果您展示了您的尝试并包含了 MCVE,这甚至可能是一个赞成的问题(这是一个很好的问题)。见this guide
  • for 循环中使用 [ -e "$file" ] ||继续

标签: bash shell mv


【解决方案1】:

欢迎来到 SO。

为什么你不想要这个错误?

如果您只是不想看到该错误,那么您可以随时使用2>/dev/null 将其丢弃,但请不要这样做。并非每个错误都是您所期望的,这是调试噩梦。您可以使用2>$logpath 将其写入日志,然后构建逻辑以读取它以确保它没问题,并相应地忽略或响应--

mv *.json /dir/ 2>$someLog
executeMyLogParsingFunction # verify expected err is the ONLY err

如果是因为您有set -etrap,并且您知道mv 失败也没关系(这可能不是因为没有文件!) ,那么你就可以使用这个技巧了-

mv *.json /dir/ || echo "(Error ok if no files found)"

mv *.json /dir/ ||: # : is a no-op synonym for "true" that returns 0

https://www.gnu.org/software/bash/manual/html_node/Conditional-Constructs.html

(如果它只是因为 mv 返回非零作为最后一个命令而失败,您还可以添加显式 exit 0,但也不要这样做 - 修复实际问题而不是修补症状。这些其他解决方案中的任何一个都应该处理这个问题,但我想指出,除非有 set -etrap 捕获错误,否则它不应该导致脚本失败,除非它是最后一个命令。)

最好是专门处理您预期的问题,而不禁用对其他问题的错误处理。

shopt -s nullglob # globs with no match do not eval to the glob as a string
for f in *.json; do mv "$f" /dir/; done # no match means no loop entry

参考https://www.gnu.org/software/bash/manual/html_node/The-Shopt-Builtin.html
或者如果你不想使用shopt

for f in *.json; do [[ -e "$f" ]] && mv "$f" /dir/; done

请注意,我只是在测试存在性,因此这将包括任何匹配项,包括目录、符号链接、命名管道……您可能需要[[ -f "$f" ]] && mv "$f" /dir/

参考https://www.gnu.org/software/bash/manual/html_node/Bash-Conditional-Expressions.html

【讨论】:

    【解决方案2】:

    这是意料之中的行为——这就是 为什么当没有匹配项时,shell 会保留 *.json 未扩展,以允许 mv 显示有用的错误。

    如果您不希望这样,您可以随时自行检查文件列表,然后再将其传递给mv。作为一种适用于所有符合 POSIX 标准的 shell 的方法,而不仅仅是 bash:

    #!/bin/sh
    
    # using a function here gives us our own private argument list.
    # that's useful because minimal POSIX sh doesn't provide arrays.
    move_if_any() {
      dest=$1; shift  # shift makes the old $2 be $1, the old $3 be $2, etc.
      # so, we then check how many arguments were left after the shift;
      # if it's only one, we need to also check whether it refers to a filesystem
      # object that actually exists.
      if [ "$#" -gt 1 ] || [ -e "$1" ] || [ -L "$1" ]; then
        mv -- "$@" "$dest"
      fi
    }
    
    # put destination_directory/ in $1 where it'll be shifted off
    # $2 will be either nonexistent (if we were really running in bash with nullglob set)
    # ...or the name of a legitimate file or symlink, or the string '*.json'
    move_if_any destination_directory/ *.json
    

    ...或者,作为一种更特定于 bash 的方法:

    #!/bin/bash
    
    files=( *.json )
    if (( ${#files[@]} > 1 )) || [[ -e ${files[0]} || -L ${files[0]} ]]; then
      mv -- "${files[@]}" destination/
    fi
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-10-27
      • 2017-01-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-11-30
      • 2012-12-16
      相关资源
      最近更新 更多