有条件地将命令的输出定向到 bash 中的 /dev/null
Conditionally directing a command's output to /dev/null in bash
我有以下 bash 脚本:
flag=false
command_name \
$( flag == false && printf %s '>/dev/null')
我预计终端没有输出,但我还是得到了一些。如果我将输出重定向到与 command-name
在同一行的 /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')
因为我 运行 这个工具和它按预期工作。我不认为它可能是一个错误流。
有条件地重定向标准输出
重定向是 shell 语法——它们必须在 在 参数扩展之前的解析阶段被识别,因此您不能通过变量扩展生成它们(不提交 evil)。
你可以做的(在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" ]]
进行精确匹配)。参见 the bash-hackers' wiki on the conditional expression。
- 在 bash 4.1 或更高版本中,
exec {fd_varname}>file
打开 file
,并将指向该文件的文件描述符编号放入变量 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>&-
到关闭它。
有条件地安全生成参数列表
请参阅 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[@]}"
- 参见 BashPitfalls #1 describing why
$(find ...)
(like $(ls ...)
) is unsafe, and Using Find 最佳实践。
- 请参阅 BashFAQ #24 了解为什么使用
while read ...; do ...; done < <(find ...)
而不是 find ... | while read ...; do ...; done
。
我有以下 bash 脚本:
flag=false
command_name \
$( flag == false && printf %s '>/dev/null')
我预计终端没有输出,但我还是得到了一些。如果我将输出重定向到与 command-name
在同一行的 /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')
因为我 运行 这个工具和它按预期工作。我不认为它可能是一个错误流。
有条件地重定向标准输出
重定向是 shell 语法——它们必须在 在 参数扩展之前的解析阶段被识别,因此您不能通过变量扩展生成它们(不提交 evil)。
你可以做的(在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" ]]
进行精确匹配)。参见 the bash-hackers' wiki on the conditional expression。 - 在 bash 4.1 或更高版本中,
exec {fd_varname}>file
打开file
,并将指向该文件的文件描述符编号放入变量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>&-
到关闭它。
有条件地安全生成参数列表
请参阅 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[@]}"
- 参见 BashPitfalls #1 describing why
$(find ...)
(like$(ls ...)
) is unsafe, and Using Find 最佳实践。 - 请参阅 BashFAQ #24 了解为什么使用
while read ...; do ...; done < <(find ...)
而不是find ... | while read ...; do ...; done
。