Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Fish command substitution doesn't work like in bash or zsh

Tags:

fish

I have stumbled on a problem with the fish shell (which is my favorite shell) when I am trying to use command substitution:

gcc (pkg-config --libs --cflags gtk+-2.0 cairo) -o drawing_widget drawing_widget.c 
gcc: erreur: unrecognized command line option ‘-pthread -I/usr/include/gtk-2.0 
-I/usr/lib/gtk-2.0/include -I/usr/include/pango-1.0 -I/usr/include/atk-1.0 -I/usr/include/gdk-pixbuf-2.0 
-I/usr/include/libpng16 -I/usr/include/pango-1.0 -I/usr/include/cairo -I/usr/include/glib-2.0 
-I/usr/lib/glib-2.0/include -I/usr/include/pixman-1 -I/usr/include/freetype2 
-I/usr/include/libpng16 -I/usr/include/harfbuzz -I/usr/include/freetype2 -I/usr/include/harfbuzz 
-I/usr/include/libdrm -I/usr/include/libpng16 -lgtk-x11-2.0 -lgdk-x11-2.0 -lpangocairo-1.0 -latk-1.0 
-lgdk_pixbuf-2.0 -lgio-2.0 -lpangoft2-1.0 -lpango-1.0 -lgobject-2.0 -lglib-2.0 -lfontconfig -lfreetype -lcairo ’

I have tested with both bash and zsh and the equivalent comment works:

gcc $(pkg-config --libs --cflags gtk+-2.0 cairo) -o drawing_widget drawing_widget.c
like image 483
cedlemo Avatar asked Jan 24 '15 18:01

cedlemo


1 Answers

The relevant difference is called "word splitting," which is how the result of a variable expansion or command substitution is turned into multiple arguments.

In bash and zsh, word splitting occurs on all whitespace. Example:

> for i in $(echo 1 2 3) ; do echo $i; done
1
2
3

In fish, word splitting occurs only on newlines:

> for i in (echo 1 2 3); echo $i; end
1 2 3

In the above, the loop only runs once, with $i set to '1 2 3'. The advantage of the fish behavior is that filenames with spaces, etc. don't cause problems like they do in bash.

pkg-config outputs space-separated text:

> pkg-config --libs --cflags libcurl libssl
-lcurl -lssl -lcrypto -lz

So it's relying on bash's word splitting behavior. (But you'd be in trouble if any flags needed embedded whitespace.)

To get the same effect in fish, you can replace spaces with newlines. tr is a good tool for that:

pkg-config --libs --cflags libcurl libssl | tr -s ' ' \n

The -s flag effectively cleans up a trailing space that pig-config outputs.

like image 118
ridiculous_fish Avatar answered Oct 18 '22 16:10

ridiculous_fish