有条件地指挥命令';s输出到bash中的/dev/null

有条件地指挥命令';s输出到bash中的/dev/null,bash,terminal,output-redirect,Bash,Terminal,Output Redirect,我有以下bash脚本: flag=false command_name \ $( flag == false && printf %s '>/dev/null') 我希望在终端没有输出,但我仍然得到一些。如果我将输出重定向到与命令名位于同一行的/dev/null,而不进行扩展,那么它将被抑制 命令是来自android SDK的dx工具 编辑1: 下面是脚本中的代码 dx \ --dex \ $( ( (( flag_v == 1 )) || (( f

我有以下bash脚本:

flag=false
command_name \
$(  flag == false  && printf %s '>/dev/null') 
我希望在终端没有输出,但我仍然得到一些。如果我将输出重定向到与
命令名
位于同一行的
/dev/null
,而不进行扩展,那么它将被抑制

命令是来自android SDK的dx工具

编辑1: 下面是脚本中的代码

dx \
    --dex \
    $( ( (( flag_v == 1 )) || (( flag_v == 'd' ))) && printf %s '--verbose') \
    --no-strict \
    --output="../"$app_name.jar \
    $(find . -type f -name '*.class') \
    $( $dexflag == false && printf %s '>/dev/null')
当我运行该工具时,它按预期工作。我不认为这可能是一个错误流。

有条件地重定向Stdout 重定向是shell语法——必须在参数扩展之前的解析阶段识别重定向,因此不能通过变量扩展(不提交)生成重定向

您可以做的(在bash 4.1或更高版本中)是无条件重定向,但要更改重定向的内容:

注:

  • 字符串比较以
    [[$var=$pattern]]
    的形式进行(或
    [[$var=“$string”]]]
    进行精确匹配)。看
  • 在bash 4.1或更高版本中,
    exec{fd_varname}>文件
    打开
    文件
    ,并将指向该文件的文件描述符编号放入变量
    fd_varname
    exec{fd_varname}>&-
    关闭编号存储在
    fd_varname
    中的文件描述符
  • 对于较旧版本的bash,您仍然可以执行此逻辑,但是您需要手动执行此操作,而不是自动分配文件描述符编号,手动分配一个未使用的FD编号,该编号不是0、1或2中的任何一个(为stdin、stdout和stderr保留)。因此,在这种情况下,
    if
    分支中的
    exec 3>/dev/null
    exec 3>&1
    ,在
    dex
    命令上的
    &3
    exec 3>关闭它

有条件地安全生成参数列表 请参阅以进行长时间的讨论。不过,简而言之:除了重定向到
/dev/null
,还有一个简单的更改需要使其与最佳实践保持一致:使用数组

#!/bin/bash

args=( )

case $flag_v in
  1|d) args+=( --verbose ) ;;
esac

while IFS= read -r -d '' filename; do
  args+=( "$filename" )
done < <(find . -type f -name '*.class' -print0)

dx --dex --no-strict --output="../$app_name.jar" "${args[@]}"
#/bin/bash
args=()
案例$flag_v in
1 | d)args+=(-verbose);;
以撒
而IFS=read-r-d“”文件名;做
args+=(“$filename”)
done<有条件重定向标准输出
重定向是shell语法——必须在参数扩展之前的解析阶段识别重定向,因此不能通过变量扩展(不提交)生成重定向

您可以做的(在bash 4.1或更高版本中)是无条件重定向,但要更改重定向的内容:

注:

  • 字符串比较以
    [[$var=$pattern]]
    的形式进行(或
    [[$var=“$string”]]]
    进行精确匹配)。看
  • 在bash 4.1或更高版本中,
    exec{fd_varname}>文件
    打开
    文件
    ,并将指向该文件的文件描述符编号放入变量
    fd_varname
    exec{fd_varname}>&-
    关闭编号存储在
    fd_varname
    中的文件描述符
  • 对于较旧版本的bash,您仍然可以执行此逻辑,但是您需要手动执行此操作,而不是自动分配文件描述符编号,手动分配一个未使用的FD编号,该编号不是0、1或2中的任何一个(为stdin、stdout和stderr保留)。因此,在这种情况下,
    if
    分支中的
    exec 3>/dev/null
    exec 3>&1
    ,在
    dex
    命令上的
    &3
    exec 3>关闭它

有条件地安全生成参数列表 请参阅以进行长时间的讨论。不过,简而言之:除了重定向到
/dev/null
,还有一个简单的更改需要使其与最佳实践保持一致:使用数组

#!/bin/bash

args=( )

case $flag_v in
  1|d) args+=( --verbose ) ;;
esac

while IFS= read -r -d '' filename; do
  args+=( "$filename" )
done < <(find . -type f -name '*.class' -print0)

dx --dex --no-strict --output="../$app_name.jar" "${args[@]}"
#/bin/bash
args=()
案例$flag_v in
1 | d)args+=(-verbose);;
以撒
而IFS=read-r-d“”文件名;做
args+=(“$filename”)

done<通过运行代码,(使用#!/bin/bash作为第一行),然后如果仍然存在问题,请使用没有语法问题的代码更新Q。另外,您知道
std error
的概念吗。您还需要将该流重定向到
/dev/null
。试试
…>/dev/null 2>&1
(我没有否决你的Q)。祝你好运。扩展的结果,例如
$()
,不会被解析为代码。因此,如果这些结果本身包含扩展,它们将不会得到尊重。这是一个特性,而不是一个bug——否则编写处理不受信任数据的shell脚本将是一场噩梦……上面假设
$dexflag==false
是一个有效的语句,而事实并非如此。(如果
dexflag
为空,它将作为命令运行
==false
;如果
true
,它将作为命令运行
true==false
;由于
true
命令忽略您的参数,结果将始终为真;如果
$dexflag
包含
false
,那么
false==false
将始终为真。)返回false,因为
false
命令同样根本不查看其参数)。并且
(())
是算术上下文;你不能在那里进行字符串比较(如果允许的话,它会将字符串作为它们命名的变量的数值进行计算)。(请参阅标记的dupe,顺便说一句——这是一个很好的例子,说明了一个问题应该是什么样的,用尽可能简单的代码来显示问题,可以在不需要任何工具/设置的情况下运行),(使用#!/bin/bash作为第一行),然后如果您仍然有问题,请使用没有语法问题的代码更新您的Q。另外,您是否知道
std error
的概念。您还需要将该流重定向到
/dev/null
。尝试
..>/dev/null 2>&1
(我没有对您的Q投反对票)。祝你好运。扩展的结果(如
$()
)不会解析为代码。因此,如果这些结果