程序结束时的Bash输出

程序结束时的Bash输出,bash,Bash,我不熟悉bash脚本,现在正在编写一个bash脚本,它应该使用scp命令从服务器下载一个文件列表。但是,不能保证文件在那里,因此我希望能够输出未找到的文件列表。目前,我这样做是为了输出错误消息: for FILENAME in $@ do scp $SERVER:/home/usr/$FILENAME . if [ $? -ne 0 ] then echo "WARNING: $FILENAME was not found in $SERVER." fi done 据我所知,上

我不熟悉bash脚本,现在正在编写一个bash脚本,它应该使用scp命令从服务器下载一个文件列表。但是,不能保证文件在那里,因此我希望能够输出未找到的文件列表。目前,我这样做是为了输出错误消息:

for FILENAME in $@ do
scp $SERVER:/home/usr/$FILENAME .
  if [ $? -ne 0 ] then
    echo "WARNING: $FILENAME was not found in $SERVER."
  fi
done
据我所知,上面的代码是有效的,但我遇到的问题是,由于scp的工作方式,屏幕上已经有大量的文本(因为每个scp命令将显示100%下载的行),我可能会错过一两条警告消息。有没有一种简单的方法可以让我在最后打印所有警告消息,列出哪些文件没有找到

编辑:我忘了澄清为什么我使用echo而不是默认的“未找到文件”——如果我的代码一开始找不到它,它实际上应该在多个位置查找。所以,更完整的版本看起来像这样:

for FILENAME in $@ do
scp $SERVER:/home/usr/$FILENAME .
  if [ $? -ne 0 ] then
      scp $SERVER:/home/usr/documents/$FILENAME .
      if [ $? -ne 0 ] then
         scp $SERVER:/home/usr/documents/local/$FILENAME .
         if [ $? -ne 0 ] then
           echo "WARNING: $FILENAME was not found in $SERVER."
         fi
      fi
  fi
done

如果它在第一个位置没有找到它,这很好,但我只希望它在任何位置都找不到它时抛出一个错误。

您可以将
scp
命令的stderr重定向到一个文件,然后在脚本末尾将该文件导出:

for FILENAME in $@ do
scp $SERVER:/home/usr/$FILENAME . 2>> /some/dir/error.log
  if [ $? -ne 0 ] then
    echo "WARNING: $FILENAME was not found in $SERVER."
  fi
done

cat /some/dir/error.log
rm /some/dir/error.log
最简单的(虽然不是最有效的解决方案)是在最后检查文件是否存在

将其添加到原始循环之后:

for FILENAME in $@ do
    if [ -s "$FILENAME" ] then
        echo "WARNING: $FILENAME was not found in $SERVER." >&2
    fi
done
或者,如果正常的scp输出不有趣(并且您不关心其他潜在的scp故障),则原始循环可能会变成:

for FILENAME in $@ do
scp -q $SERVER:/home/usr/$FILENAME . 2>/dev/null
  if [ $? -ne 0 ] then
      scp -q $SERVER:/home/usr/documents/$FILENAME . 2>/dev/null
      if [ $? -ne 0 ] then
         scp -q $SERVER:/home/usr/documents/local/$FILENAME . 2>/dev/null
         if [ $? -ne 0 ] then
           echo "WARNING: $FILENAME was not found in $SERVER."
         fi
      fi
  fi
done
如果您确实想要scp输出(正常或错误或两者),但希望在结尾处有一个简洁的缺失文件列表,您可以这样做:

missing_files=()
for FILENAME in $@ do
scp $SERVER:/home/usr/$FILENAME .
  if [ $? -ne 0 ] then
      scp $SERVER:/home/usr/documents/$FILENAME .
      if [ $? -ne 0 ] then
         scp $SERVER:/home/usr/documents/local/$FILENAME .
         if [ $? -ne 0 ] then
           missing_files+=("$FILENAME")
         fi
      fi
  fi
done

echo 'Missing files:'
printf %s\\n "${missing_files[@]}"

使用
-q
告诉
scp
保持安静?在结尾再次循环参数,看看本地文件是否存在?如果附加到数组变量并在末尾打印该数组,是否在该
中不回显?改为回显到标准错误,并将其传输到文件或从
scp
将标准输出传输到
/dev/null
?@Etan Reisner:似乎
-q
只隐藏了进度表,而不是stderr。来自scp的关于文件不存在/失败的stderr可能是OP实际需要的信息(因为它为他们做了这项工作). 除非scp也在stderr上填充了其他非故障信息。@EtanReisner我只需要知道在列出的任何位置都找不到哪些文件(请参阅原始帖子中的编辑),所以我不希望看到每一条错误消息,因为如果在第一个目录中找不到该文件,但后来在第二个或第三个目录中找到该文件,然后第一次失败的错误消息只会让我失望,因为最终我找到了文件,只是没有找到我最初想要的地方。好的。所以
-q
是不够的,但是如果你不关心进度表,它仍然是有用的,如果你也不关心scp错误,那么你可以将它们全部重定向到
2>/dev/null
,只在最后输出错误。你可以做我建议的其他事情。接得好。我们处于一个循环中。更正。2>>中的数字2是什么意思?2>/some/dir/error.log似乎将所有输出都放入一个日志文件中,然后在最后输出,但我只需要知道在所有列出的位置(请参阅我的原始帖子上的编辑)找不到哪些文件Linux上的命令行程序有两个输出,默认情况下都会转到命令行。Stdout,这是程序中正常的有声谈话。Stderr是程序报告的错误。您可以使用
(覆盖文件)或
>
(附加到文件)将其中一个或两个重定向到文件<代码>1>
是stderr重定向,
2>
是stderr重定向。您也可以使用
&>
重定向这两个命令。@jnevil接着说,如果我使用2>>,它从您的解释重定向stderr,这会影响我下面的行,检查退出代码的if语句吗?或者重定向stderr不会影响仍然返回的退出代码吗?这不会影响错误代码检查。它只是重定向消息。我也为迟来的回复感到抱歉。最后一封正是我想要的;非常感谢。