Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Why does xargs under fish not accept {} as a replstr like it does with bash?

    find . | xargs -I {} grep pat {}
On OS X fish this gives "xargs: replstr may not be empty" and on Linux fish I get "xargs: command too long". Using % as the replstr for example does work though.


The beauty of fish is that it handles lists much better than bash - it kind of has xargs "baked in". If I understand the example correctly, it finds every file under the current directory and greps for "pat" in each file.

In fish you could do this:

  grep pat (find .)
... or this:

  for i in (find .)
    grep pat $i
  end
The first example would work correctly in fish, but AFAIK it wouldn't work in bash. The is because every line from the command substitution is automatically escaped and quoted in fish. The small drawback is that a symbol-heavy commandline sometimes needs a few extra \ escapes - the power to handle lists of lines (i.e. lines from stdin or from command substitution) is bought for a little extra escaping. And it's a good deal IMO.

And the for loop in fish is so elegant and convenient that it's worth using for small random stuff.

(Everything I say is pending that I understand the find/xargs/grep example!)


Yep, you understood it fine. ('pat' was short for 'pattern'. It was just an example)

Wow, that 'autoescaping the commands in parens' syntax is great. But it doesn't seem to be list related. For example: grep pattern (echo "foo.txt") just passes the result from the echo to grep. It's grep which is doing the right thing with a list, right? Still this is interesting. So fish stuff isn't necessarily written left to right and joined with pipes, instead it's written in nested form like in a more modern langauge.

Alas you still need to use the "find | grep" technique in fish because of the argument size limit. For example:

    grep pattern (find .)
results in:

Failed to execute process '/usr/bin/grep'. Reason: The total size of the argument and environment lists 34kB exceeds the operating system limit of 34kB. Try running the command again with fewer arguments.

The equivalent in bash gives you:

-bash: /usr/bin/grep: Argument list too long


I'm not sure why the recommended replacement string to use with xargs's -I is "{}". I just use "XXX" as the replacement string and stop worrying about how the shell is interpreting metacharacters in this particular case:

    find . | xargs -I XXX grep pat XXX


Fish does brace expansion, even for empty braces. In order to actually pass braces to xargs, do:

    find . | xargs -I \{\} grep pat \{\}


OK, thanks.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: