Har*_*hiv 1 bash terminal output-redirect
我有以下 bash 脚本:
flag=false
command_name \
$( flag == false && printf %s '>/dev/null')
Run Code Online (Sandbox Code Playgroud)
我希望终端没有输出,但我仍然得到一些。如果我将输出重定向到没有扩展/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')
Run Code Online (Sandbox Code Playgroud)
当我运行该工具时,它按预期工作。我不认为这可能是一个错误流。
重定向是 shell 语法——它们必须在参数扩展之前的解析阶段被识别,所以你不能通过变量扩展来生成它们(不作恶)。
你可以做的(在 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}>&-
Run Code Online (Sandbox Code Playgroud)
笔记:
[[ $var = $pattern ]](或[[ $var = "$string" ]]进行精确匹配)。有关条件表达式,请参阅bash-hackers 的 wiki。exec {fd_varname}>file打开file并将指向该文件的文件描述符编号放入变量fd_varname. exec {fd_varname}>&-关闭其编号存储在fd_varname.exec 3>/dev/null或exec 3>&1在if分支中,>&3在dex命令上,并exec 3>&-关闭它。有关长时间讨论,请参阅BashFAQ #50。简而言之:对于重定向到 之外的所有内容/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[@]}"
Run Code Online (Sandbox Code Playgroud)
$(find ...)(如$(ls ...))不安全,以及使用 Find进入最佳实践。while read ...; do ...; done < <(find ...)使用find ... | while read ...; do ...; done.