Linux 仅在命令失败时重定向标准输出?

Linux 仅在命令失败时重定向标准输出?,linux,bash,shell,Linux,Bash,Shell,我正在编写一个bash脚本,它应该对用户“透明”。它从用户那里读取命令并截取它们,只允许bash执行其中的一些命令,具体取决于某些条件。它(基本上)是这样工作的: while true; do read COMMAND can_be_done $COMMAND if [ $? == 0 ]; then eval $COMMAND if [ $? != 0 ]; then echo "Error: command not found"

我正在编写一个bash脚本,它应该对用户“透明”。它从用户那里读取命令并截取它们,只允许bash执行其中的一些命令,具体取决于某些条件。它(基本上)是这样工作的:

while true; do
   read COMMAND
   can_be_done $COMMAND
   if [ $? == 0 ]; then
      eval $COMMAND
      if [ $? != 0 ]; then
         echo "Error: command not found"
      fi
   fi
done
while true; do
   read -e COMMAND
   if can_be_done "$COMMAND"; then
      eval "$COMMAND"
   fi
done
问题是,当命令失败时,您还可以将内容打印到控制台。但是,如果我将结果保存在一个变量中,并且只在它没有失败时打印它,就像这样:

RESULT=$(eval $COMMAND)
然后还有另一个问题:特殊格式丢失(例如,“ls--color”不再显示颜色)


我的问题是:如果成功,有没有办法让命令打印到STDOUT,如果失败则打印到/dev/null?

您真的需要第二部分,用错误消息替换命令的输出?Linux命令打印自己的错误消息,这些消息不一定是“找不到命令”。您可能会隐藏真正的错误(权限被拒绝、找不到文件、内存不足、segfault等),并经常显示错误消息(未找到命令)

如果删除该检查,可以将循环简化为以下内容:

while true; do
   read COMMAND
   can_be_done $COMMAND
   if [ $? == 0 ]; then
      eval $COMMAND
      if [ $? != 0 ]; then
         echo "Error: command not found"
      fi
   fi
done
while true; do
   read -e COMMAND
   if can_be_done "$COMMAND"; then
      eval "$COMMAND"
   fi
done
  • read-e
    使用readline获取命令,使提示符更像shell(例如,对于历史记录,↑和&downarow;)
  • 命令;如果[$?==0];然后
    更习惯地写为
    if;然后
  • 引用确保特殊字符和空格得到正确处理

假设该命令的运行成本不是很高,您可以执行以下操作:

   test `ls /mooo 2>/dev/null` || echo moo not found
只有当命令以0退出时,test才会返回true,在这种情况下,ls是命令。您也可以将其放入if语句中,如下所示:

if [ `ls /moo 2>/dev/null` ];then 
  echo moo is a folder
fi

我强烈主张你不应该这样做。如果不想看到输出,请将其重定向到
/dev/null
。如果确实希望看到错误,请不要重定向stderr。如果您使用的程序在stdout而不是stderr上打印错误消息,请修复该程序!错误消息属于stderr。请注意,这意味着您的程序已被破坏,应该是这样的:

 echo "Error: command not found" >&2

我不确定这是否是第1条规则,但它肯定属于前10条,这可能是最常违反的规则:
错误消息属于stderr
。在标准输出上打印错误消息的程序已损坏。

如果为false>/dev/null;然后回波1;else-2;fi 2>/dev/null

将输出
2

如果为true>/dev/null;然后回波1;else-2;fi 2>/dev/null

将输出
1

删除
/dev/null
,将命令也打印到stdout

比如说
if-echo 123;然后回波1;else-2;fi 2>/dev/null

将输出
123
&
1

颜色对我来说并没有丢失。结果=$(评估ls——颜色);echo“$RESULT”@dogbane
ls--color
表示
ls--color=always
。通常
ls
的别名是
ls--color=auto
ls--color=tty
,也就是说,它只在stdout是终端时打印彩色代码(
isatty
)。我刚刚意识到,你说得对!但由于某种原因,“ls--color=auto”确实存在(这是ls使用的别名)。我删除了“=auto”,现在这种方法会显示颜色。人们会认为,如果命令失败,用户需要尽可能多的信息。那么为什么要掩盖这些信息呢?@demandawid我不会改变这个别名。如果您使用
alias ls='ls--color'
,那么在管道中使用
ls
会有问题(当stdout不是tty时)。谢谢您的建议。正如您可能知道的,我对bash脚本非常陌生<代码>如果ls;然后检查ls的退出代码
if[`ls`]
等同于
if[-n`ls`]
;它检查ls没有输出任何内容。