我有以下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')
当我运行该工具时,它按预期工作。我不认为它可能是错误流。
答案 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。exec {fd_varname}>file
打开file
,并将文件描述符编号指向变量fd_varname
中的该文件。 exec {fd_varname}>&-
关闭其编号存储在fd_varname
。exec 3>/dev/null
分支中可能是exec 3>&1
或if
,>&3
命令中可能是dex
,exec 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 ...)
$(ls ...)
(如while read ...; do ...; done < <(find ...)
)不安全,BashPitfalls #1进入最佳做法。find ... | while read ...; do ...; done
代替Map
。