在bash中有条件地将命令的输出定向到/ dev / null

时间:2017-11-29 12:03:04

标签: bash terminal output-redirect

我有以下bash脚本:

flag=false
command_name \
$(  flag == false  && printf %s '>/dev/null') 

我希望终端没有输出,但我仍然得到一些。如果我将输出重定向到与/dev/null相同的行上的command-name而没有该扩展,则会被抑制。

命令是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')

当我运行该工具时,它按预期工作。我不认为它可能是错误流。

1 个答案:

答案 0 :(得分:4)

有条件地重定向标准输出

重定向是shell语法 - 它们必须在参数扩展之前的解析阶段被识别,因此您无法通过变量扩展生成它们(不提交{{3} })。

可以做什么(在bash 4.1或更高版本中)有一个无条件的重定向,但它重定向到的东西改变了:

# Create an out_fd variable that points to stdout (FD 1) if dexflag != "false", or to a new
# handle on /dev/null otherwise
if [[ $dexflag = false ]]; then
  exec {out_fd}>/dev/null # maybe put 2>&1 as well to suppress stderr
else
  out_fd=1 # use FD 1 (stdout)
fi

# run dex with its stdout redirected to the FD number in "out_fd"
dex ... >&"$out_fd"

# if out_fd is not stdin/stdout/stderr, then go ahead and close it when done.
(( out_fd > 2 )) && exec {out_fd}>&-

注意:

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

有条件地安全地生成参数列表

请参阅the bash-hackers' wiki on the conditional expression进行长时间的讨论。简而言之,除了重定向到#!/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[@]}" 之外的所有内容之外,还需要进行一项简单的更改,以使其与最佳实践保持一致:使用数组。

$(find ...)
  • 请参阅BashFAQ #50,说明为什么$(ls ...)(如while read ...; do ...; done < <(find ...))不安全,BashPitfalls #1进入最佳做法。
  • 请参阅Using Find了解为何使用find ... | while read ...; do ...; done代替Map