我有一个脚本(file_redirection.sh),我尝试了各种组合来获得我想要的东西:
#!/bin/bash
echo "cat " $*
echo "cat $*"
echo "cat $@"
echo "cat " $@
Run Code Online (Sandbox Code Playgroud)
我希望能够跑
file_redirection.sh < tmp_file
Run Code Online (Sandbox Code Playgroud)
并让它显示
"cat < tmp_file"
Run Code Online (Sandbox Code Playgroud)
那可能吗?
不,那是不可能的.在<命令行上被shell脚本曾经运行前解释.你需要逃避<它才能进入你的脚本.例如:
file_redirection.sh \< tmp_file
Run Code Online (Sandbox Code Playgroud)
将生成您正在寻找的输出,但不会执行任何文件重定向.
你问“它是如何工作的”。UNIX 进程是使用称为 的操作创建的fork。这会获取当前进程的副本,并以非常有效的方式几乎完全按照原样复制它。复制还包括文件描述符表,其中 stdin、stdout、stderr、live。
当您进行重定向时,shell 会分叉,然后在子进程中更改它自己的文件描述符 (fd) 表。然后它在同一进程中使用相同的 fd 表运行新脚本。使用传统机制,进程唯一可以检查的是 stdin 是否连接到终端。在 C 中它使用,isatty()而在 bash 中你可以if [[ -t 0 ]]...(零是 stdin 的 fd)。
在 Linux(如果您使用的是 Linux)中,您有一个附加选项,fd 表以可读的形式显示在/proc/$$/fd($$ 给出当前进程 ID) 中。 ls -l /proc/$$/fd你会明白我的意思。
那么,我被重定向了吗?
if [[ -t 0 ]] # is stdin a terminal?
then
suffix=""
else
line=$(ls -l /proc/$$/fd/0)
file="${line##*-> }"
suffix="< $file"
fi
echo "cat $suffix"
Run Code Online (Sandbox Code Playgroud)
在命令行上:
/home/user1$ file_redirection.sh < tmp_file
cat < /home/qa/tmp_file
Run Code Online (Sandbox Code Playgroud)
但。你到底为什么要这样做?