我有一个脚本,使用从SO 上的问答中获取的以下方法将文件名解析为数组:
unset ARGS
ARGID="1"
while IFS= read -r -d $'\0' FILE; do
ARGS[ARGID++]="$FILE"
done < <(find "$@" -type f -name '*.txt' -print0)
Run Code Online (Sandbox Code Playgroud)
这很好用,可以完美地处理所有类型的文件名变化。但是,有时我会将一个不存在的文件传递给脚本,例如:
$ findscript.sh existingfolder nonexistingfolder
find: `nonexistingfile': No such file or directory
...
Run Code Online (Sandbox Code Playgroud)
在正常情况下,我会让脚本用类似的东西捕获退出代码,RET=$?并用它来决定如何继续。这似乎不适用于上面的过程替换。
在这种情况下,正确的程序是什么?如何捕获返回码?是否有其他更合适的方法来确定替换过程中是否出现问题?
在 Bash 版本 4.2.47(1)-release 中,当我尝试连接来自 HERE-dcoument 的格式化文本时,如下所示:
cat <(fmt --width=10 <<FOOBAR
(I want the surrounding parentheses to be part of the HERE-document)
(Even the preceding unbalanced parenthesis should be part of it.
FOOBAR
) # I want this paranthesis to end the process substitution.
Run Code Online (Sandbox Code Playgroud)
我收到以下错误:
bash: bad substitution: no closing `)' in <(fmt --width=10 <<FOOBAR
(I want the surrounding parentheses to be part of the HERE-document)
(Even the preceding unbalanced parenthesis should be part of it.
FOOBAR
)
Run Code Online (Sandbox Code Playgroud)
此外,我不想引用 HERE …
这
echo one; echo two > >(cat); echo three;
Run Code Online (Sandbox Code Playgroud)
命令给出了意外的输出。
我读到:如何在 bash 中实现进程替换?以及互联网上有关进程替换的许多其他文章,但不明白为什么它会这样。
预期输出:
one
two
three
Run Code Online (Sandbox Code Playgroud)
实际输出:
prompt$ echo one; echo two > >(cat); echo three;
one
three
prompt$ two
Run Code Online (Sandbox Code Playgroud)
此外,从我的角度来看,这两个命令应该是等效的,但它们不是:
##### first command - the pipe is used.
prompt$ seq 1 5 | cat
1
2
3
4
5
##### second command - the process substitution and redirection are used.
prompt$ seq 1 5 > >(cat)
prompt$ 1
2
3
4
5
Run Code Online (Sandbox Code Playgroud)
为什么我认为,它们应该是一样的?因为,两者都通过匿名管道将seq输出连接到cat …
当我这样做时:
sudo wpa_supplicant -D nl80211,wext -i wlp4s0 -c <(wpa_passphrase "some ssid" "password")
Run Code Online (Sandbox Code Playgroud)
我得到
Successfully initialized wpa_supplicant
Failed to open config file '/dev/fd/63', error: No such file or directory
Failed to read or parse configuration '/dev/fd/63'
Run Code Online (Sandbox Code Playgroud)
有任何想法吗?
在 bash 中,我想将当前工作目录分配给一个变量。使用子shell,我可以做到这一点。
var=$(pwd)
echo $var
/home/user.name
Run Code Online (Sandbox Code Playgroud)
如果我像这样使用进程替换:
var=<(pwd)
echo $var
/dev/fd/63
Run Code Online (Sandbox Code Playgroud)
我知道进程替换主要在程序不接受 STDIN 时使用。我不清楚进程替换究竟做了什么以及为什么它分配/dev/fd/63给var.
我没有太多使用 tee 的经验,所以我希望这不是很基本。
在查看了这个问题的一个答案后,我遇到了一个奇怪的行为tee。
为了让我输出第一行和找到的行,我可以使用这个:
ps aux | tee >(head -n1) | grep syslog
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
syslog 806 0.0 0.0 34600 824 ? Sl Sep07 0:00 rsyslogd -c4
Run Code Online (Sandbox Code Playgroud)
然而,我第一次运行这个(在 zsh 中)结果是错误的顺序,列标题低于 grep 结果(但这并没有再次发生),所以我尝试交换命令:
ps aux | tee >(grep syslog) | head -n1
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
Run Code Online (Sandbox Code Playgroud)
只打印第一行,没有别的!我可以使用 tee 重定向到 grep,还是我以错误的方式执行此操作?
当我输入这个问题时,第二个命令实际上对我有用一次,我再次运行了五次,然后返回到一行结果。这只是我的系统吗?(我在 tmux 中运行 zsh)。
最后,为什么第一个命令没有显示“grep syslog”作为结果(只有一个结果)?
这里的控制是没有的 grep tee
ps …Run Code Online (Sandbox Code Playgroud) 下面一行很明显:
echo "bla" | foo | bar
Run Code Online (Sandbox Code Playgroud)
但是下面的人也这样做吗?
echo "bla" | bar <(foo)
echo "bla" | bar < <(foo)
Run Code Online (Sandbox Code Playgroud)
哪个foo和bar从标准输入读取“bla”,为什么?
我的意思是,当然,我可以编写代码并检查它,但我不确定它是定义的行为还是我正在利用我不应该依赖的功能。
在 bash 提示符下,可以使用伪文件执行 diff:
diff <(echo test) <(echo test)
Run Code Online (Sandbox Code Playgroud)
将其按原样添加到 Makefile 失败:
all:
diff <(echo test) <(echo test)
Run Code Online (Sandbox Code Playgroud)
错误(提示:/bin/sh 指向此系统上的 /bin/bash):
/bin/sh: -c: line 0: syntax error near unexpected token `('
/bin/sh: -c: line 0: `diff <(echo test) <(echo test)'
Run Code Online (Sandbox Code Playgroud)
这是什么意思,有没有办法在不使用临时文件的情况下仍然区分两个输出?
我正在研究另一个问题,当我意识到我不明白幕后发生了什么,这些/dev/fd/*文件是什么以及子进程如何打开它们时。
大概尝试多次ssh访问,但在第一次读取后就被销毁了:fdfd
# ssh -i <(echo $KEY) user@example.com
Warning: Identity file /dev/fd/11 not accessible: Bad file descriptor.
user@example.com: Permission denied (publickey).
Run Code Online (Sandbox Code Playgroud)
有没有其他方法而不写入/删除临时文件?