检查是否没有命令行参数且 STDIN 为空

Vit*_*sty 6 bash shell-script

如何在 Bash 脚本中检查没有提供命令行参数或 STDIN?

我的意思是如果我跑:

#> ./myscript.sh
... Show message "No data provided..." and exit
Run Code Online (Sandbox Code Playgroud)

或者:

#> ./myscript.sh filename.txt
... Read from filename.txt
Run Code Online (Sandbox Code Playgroud)

或者:

#> ./myscript.sh < filename.txt**
... Read from STDIN
Run Code Online (Sandbox Code Playgroud)

per*_*ror 11

这符合您的要求吗?

#!/bin/sh

if test -n "$1"; then
    echo "Read from $1";
elif test ! -t 0; then
    echo "Read from stdin"
else
    echo "No data provided..."
fi
Run Code Online (Sandbox Code Playgroud)

主要技巧如下:

  • 检测您是否有参数是通过test -n $1检查第一个参数是否存在来完成的。

  • 然后,检查是否stdin未在终端上打开(因为它通过管道传输到文件)完成test ! -t 0(检查文件描述符零(又名stdin)是否未打开)。

  • 最后,其他一切都归于最后一种情况 ( No data provided...)。


小智 5

我四处寻找无果,最后经过多次尝试和错误终于将其组合在一起。从那时起,它在许多用例中都完美地为我工作。

#!/bin/bash
### LayinPipe.sh
## Recreate "${@}" as "${Args[@]}"; appending piped input.
## Offers usable positional parameters regardless of where the input came from.
##
## You could choose to create the array with "${@}" instead following
##  any piped arguments by simply swapping the order
##   of the following two 'if' statements.

# First, check for normal positional parameters.
if [[ ${@} ]]; then
    while read line; do
        Args[${#Args[@]}]="${line}"
    done < <(printf '%s\n' "${@}")
fi

# Then, check for piped input.
if [[ ! -t 0 ]]; then
    while read line; do
        Args[${#Args[@]}]="${line}"
    done < <(cat -)
fi

# Behold the glory.
for ((a=0;a<${#Args[@]};a++)); do
    echo "${a}: ${Args[a]}"
done
Run Code Online (Sandbox Code Playgroud)
  • 示例:(充分了解不鼓励使用“ls”的输出作为输入,以显示此解决方案的灵活性。)
$ ls
: TestFile.txt 'Filename with spaces'

$ ls -1 | LayinPipe.sh "$(ls -1)"
> 0: Filename with spaces
> 1: TestFile.txt 
> 2: Filename with spaces
> 3: TestFile.txt 

$ LayinPipe.sh "$(ls -1)"
> 0: Filename with spaces
> 1: TestFile.txt 

$ ls -1 | LayinPipe.sh
> 0: Filename with spaces
> 1: TestFile.txt 

Run Code Online (Sandbox Code Playgroud)