Maybe:
readlink "/proc/$(
pgrep -P "$(xdotool getactivewindow getwindowpid)" | head -n1
)/cwd"
That is get the pid associated with the window using xdotool
, use pgrep
to get the list of children of that process, head -n1
to only select the first one, and use readlink
to get the working directory.
Will not work for every window. For instance, not for windows from remote clients or that don't provide the window manager with their PID, not for processes by other users.
Doing same strace
, you can see the differences:
With pipe
:
$ strace -c ./pipe.sh
% time seconds usecs/call calls errors syscall
------ ----------- ----------- --------- --------- ----------------
57.89 0.103005 5 20000 clone
40.81 0.072616 2 30000 10000 wait4
0.58 0.001037 0 120008 rt_sigprocmask
0.40 0.000711 0 10000 pipe
With proc-sub
:
$ strace -c ./procsub.sh
% time seconds usecs/call calls errors syscall
------ ----------- ----------- --------- --------- ----------------
85.08 0.045502 5 10000 clone
3.25 0.001736 0 90329 322 read
2.12 0.001133 0 20009 open
2.03 0.001086 0 50001 dup2
With above statistics, you can see pipe
create more child processes (clone
syscall) and spending many times to wait child process (wait4
syscall) to finish for parent process to continue executing.
Process substitution
is not. It can read directly from child processes. Process substitution
is performed at the same time with parameter and variable expansion, the command in Process Substitution
run in background. From bash manpage
:
Process Substitution
Process substitution is supported on systems that support named pipes
(FIFOs) or the /dev/fd method of naming open files. It takes the form
of <(list) or >(list). The process list is run with its input or out‐
put connected to a FIFO or some file in /dev/fd. The name of this file
is passed as an argument to the current command as the result of the
expansion. If the >(list) form is used, writing to the file will pro‐
vide input for list. If the <(list) form is used, the file passed as
an argument should be read to obtain the output of list.
When available, process substitution is performed simultaneously with
parameter and variable expansion, command substitution, and arithmetic
expansion.
Update
Doing strace with statistics from child processes:
With pipe
:
$ strace -fqc ./pipe.sh
% time seconds usecs/call calls errors syscall
------ ----------- ----------- --------- --------- ----------------
70.76 0.215739 7 30000 10000 wait4
28.04 0.085490 4 20000 clone
0.78 0.002374 0 220008 rt_sigprocmask
0.17 0.000516 0 110009 20000 close
0.15 0.000456 0 10000 pipe
With proc-sub
:
$ strace -fqc ./procsub.sh
% time seconds usecs/call calls errors syscall
------ ----------- ----------- --------- --------- ----------------
52.38 0.033977 3 10000 clone
32.24 0.020913 0 96070 6063 read
5.24 0.003398 0 20009 open
2.34 0.001521 0 110003 10001 fcntl
1.87 0.001210 0 100009 close
Best Answer
A command substitution (
$(...)
) will be replaced by the output of the command, while a process substitution (<(...)
) will be replaced by a filename from which the output of the command may be read. The command, in both instances, will be run in a subshell.In your case, the output from
pwd
in<(pwd)
may be found at/dev/fd/63
. This file ceases to exist as soon as the command that uses the process substitution has finished executing (when the assignment tovar
in your example is done).The filename returned by a process substitution is the name of a file descriptor or named pipe, not a regular file:
A common use of process substitution is to pre-sort files for the
join
command:or for removing columns from a file (here, column 2 is removed from a tab-delimited file by using
cut
twice andpaste
to stitch the result together):Process substitution is more or less a syntactical shortcut for avoiding using temporary files explicitly.
Both command substitutions and process substitutions are performed in subshells. The following shows that the environment in these subshells do not affect the parent shell's environment:
Here,
echo
gets1234
as a string argument from the command substitution.Here,
cat
get the filename of a file (named pipe/file descriptor) as its argument. The file contains the data4321
.