shell 如果没有文件匹配glob,则防止“mv”命令引发错误,例如”mv *.json /dir/

kmbjn2e3  于 2023-02-05  发布在  Shell
关注(0)|答案(3)|浏览(238)

我想将jenkins作业中创建的所有JSON文件移动到不同的文件夹。
作业可能未创建任何json文件。在这种情况下,mv命令将引发错误,因此作业将失败。
如果找不到文件,如何防止mv命令引发错误?

k5hmc34c

k5hmc34c1#

欢迎来到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
(If它的失败仅仅是因为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

tjrkku2a

tjrkku2a2#

这是预期的行为--这就是为什么当没有匹配时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
lztngnrs

lztngnrs3#

循环遍历所有json文件,并在一个行中移动每个文件(如果存在):

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

相关问题