No Bash Command Substitution?!


Forum: User Feedback
Topic: No Bash Command Substitution?!
started by: chaostic

Posted by chaostic on Jan. 07 2008,06:48
Using 3.4.4, it seems that command substitution doesn't work in DSL.

Code Sample

dsl@ttyp1[dsl]$ sudo cat Events >( grep -i "Linux" - > test.txt )
07:19:DSL 1.3.1 Released
08:02:DSL 1.4 Released.
08:09:Linux World
08:10:Linux World
08:11:Linux World
10:31:Halloween
cat: /dev/fd/63: No such file or directory


sudo, or it would hang at the end of cat, because it can not access the non-existent file.

Can't sudo mkfifo /dev/fd/63, or touch /dev/fd/63

/dev/fd points to /proc/self/fd/
/proc/self points to /proc/n/ where n changes on almost every command

Basically, there is no fifos at /dev/fd/xx and command substitution won't work.

How can I create them, or can they be added for the next maintence 3.4.9

Posted by ^thehatsrule^ on Jan. 07 2008,15:45
I'm not sure what you're trying to do... but you could try something like
Code Sample
$ cat Events | grep -i "Linux" > test.txt
or if you need stdout as well
Code Sample
$ cat Events | grep -i "Linux" | tee test.txt
Also, I don't think you're trying to do command substitution.

EDIT: manpage says process substitution.  Bash will use temporary files if /dev/fd/?? (i.e. `echo <(true)` ) doesn't exist... so your syntax is wrong?  If you need to use it, maybe try something like
Code Sample
$ grep -i "Linux" <(cat Events) > test.txt #redundant

Posted by mikshaw on Jan. 07 2008,16:45
For bash-specific command substitution, the opening parenthesis is preceded by a $:
$(grep -i "Linux" -)
You can also use backticks for compatibility with other shells:
`grep -i "Linux" -`

I think the first example from ^thehatsrule^ is most logical though.

Posted by ^thehatsrule^ on Jan. 07 2008,17:18
mikshaw: using - will require something from stdin, and using command substitution only provides output... so wouldn't that just stall?
Posted by chaostic on Jan. 08 2008,06:17
Well, I would need the command substitution to do:
Code Sample

cat /dev/ptyu1 | fgrep --line-buffered -e "New Title" -e "Icy-Name" -e "icy-url" | sed -e /"access_http debug: "/s/// -e '/Icy-Name/i\
--
' -e /"Meta-Info: icy-url"/s//"Icy-Url"/ -e /"New Title="/s//"Now Playing: "/ | tee >(grep --line-buffered "Icy-Name" | sed -e /"Icy-Name"/s/// > CurrentStation.txt) >(grep --line-buffered "Now Playing" | sed -e /"Now Playing"/s///) >(nc)


or

Code Sample
command1 | tee >(command2) >(command3) >(command4) | command5


Or in simpler terms, allow for multiple programs writing multiple files from the same base file read, which when using pipes, named pipes, or pseudo-terminals needs to be done like this since only one program can read or write to it at a time.

Edit: The example I used in the first post was just that, an example. :/

Posted by roberts on Jan. 08 2008,16:13
They are pipes. Should be created by bash.

echo >(true)

diff <(ls -l) <(ls -a)

comm <(ls -l) <(ls -al)

sort -k 9 <(ls -l /bin) <(ls -l /usr/bin) <(ls -l /usr/X11R6/bin)

These all work fine for me.

Note bash in DSL is v2.05b, perhaps your requirements need a higher bash version?



Posted by jpeters on Jan. 08 2008,17:00
Quote (roberts @ Jan. 08 2008,11:13)
They are pipes. Should be created by bash.

echo >(true)

diff <(ls -l) <(ls -a)

comm <(ls -l) <(ls -al)

sort -k 9 <(ls -l /bin) <(ls -l /usr/bin) <(ls -l /usr/X11R6/bin)

These all work fine for me.

Note bash in DSL is v2.05b, perhaps your requirements need a higher bash version?

Initially didn't work for me either; so I found this:

Repeat-By:
   # Check that devfs(5) is mounted on /dev and execute a command
   # that uses process substitution.
   $ mount | grep devfs
   devfs on /dev (devfs, local)
   $ diff <(cat /etc/group)  <(cat /etc/group)
   diff: /dev/fd/63: No such file or directory
   diff: /dev/fd/62: No such file or directory
   $ ls /dev/fd
   0    1    2

Posted by chaostic on Jan. 08 2008,19:46
Hmm. Weird. I got it working.
Somehow
cat Events | tee >(grep -i "Linux" > test.txt)
is different then
cat Events >(grep -i "Linux" > test.txt)

This now works:
cat vlchelp | tee >(grep -i interface > test12.txt) >(grep -i log > test13.txt) | grep -i http
i.e. three outputs from one file read :D

Edit:
Looking at how process substitution works (both forwards and backwards) I know why cat wasn't working.
cat Events >( grep -i "Linux" > test.txt)
Is actually
cat Events /dev/fd/63
is
cat filename filename
Even though >() should be a pipe, but since cat wasn't meant to take an output file argument, just input file arguments.

Edit2:

I have no devfs mounted on /dev, especially since dsl has a static /dev, no?
Only devfs is usbdevfs

Posted by jpeters on Jan. 08 2008,21:08
Quote (chaostic @ Jan. 08 2008,14:46)
Edit2:

I have no devfs mounted on /dev, especially since dsl has a static /dev, no?
Only devfs is usbdevfs

Hm....seemed to work before, but haven't been able to replicate it.
Powered by Ikonboard 3.1.2a
Ikonboard © 2001 Jarvis Entertainment Group, Inc.