10

On AIX (but this happens on HP-UX as well), I have GNU ls in my path and it is also aliased as ls.

When I use xargs, it instead uses the standard Unix ls instead of the alias.

For example (flocate is a function which finds the exact path of the search subject):

flocate mirrorvg | xargs ls -lh
ls: illegal option -- h
usage: ls [-1ACFHLNRSabcdefgiklmnopqrstuxEUX] [File...]

ls -lh /usr/sbin/mirrorvg
-r-xr-x--- 1 root system 37K apr  3  2014 /usr/sbin/mirrorvg*

Why doesn't xargs use the ls alias?

Jeff Schaller
  • 66,199
  • 35
  • 114
  • 250
elbarna
  • 12,050
  • 22
  • 92
  • 170
  • 1
    What exactly does "I have GNU ls in my path" mean? Is the directory containing the GNU `ls` executable in your `$PATH` environment variable, and does it precede the directory (probably `/bin`) containing the non-GNU `ls` command? Please update your question to show us the actual value of your `$PATH`. `xargs` will execute the *first* `ls` command that it finds in a directory in your `$PATH`; it doesn't know about aliases. – Keith Thompson Apr 29 '15 at 18:34

2 Answers2

9

The command xargs is only able to run commands, not aliases. GNU parallel, however, is able to run functions:

The command must be an executable, a script, a composed
command, or a function. If it is a function you need to export
-f the function first. An alias will, however, not work (see
why http://www.perlmonks.org/index.pl?node_id=484296).

So I would recommend either:

  • Giving xargs the full path to the version of ls you want to use (or an unambiguous name, perhaps gls depending on how it was installed on your system) or, if your shell allows it,

  • Defining ls as a function (function ls { gls "$@"; }; export -f ls in bash) and using GNU parallel instead of xargs (parallel -j1 if you would like to use a single CPU).

dhag
  • 15,440
  • 4
  • 54
  • 65
  • exporting functions only works with the `bash` shell. You can use `xargs` with exported functions as well: `ls() { gls "$@"; }; export -f ls; ... | xargs bash -c '"$0" "$@"' ls` – Stéphane Chazelas Apr 29 '15 at 19:50
  • Oh, nice trick, it could be useful if one is forced to use xargs. – dhag Apr 29 '15 at 19:55
  • 1
    You can use `env_parallel` if you want to use aliases or do not want to export the function. Aliases are supported in: ash, bash, csh, dash, fish, ksh, mksh, pdksh, tcsh, zsh. Functions are supported in: bash, fish, ksh, mksh, pdksh, sh, zsh. They even work if you run commands on remote servers. https://www.gnu.org/software/parallel/env_parallel.html – Ole Tange May 20 '20 at 12:34
3

The alias substitution is done by the shell. If the shell tries to call command foo, and there is an alias foo=bar, it's the shell that substitutes the foo by bar here.

The shell only does this for commands. (Otherwise, arguments that happen to be the same as an aliased command would be replaced too.) But your ls here is not run by the shell, but an argument to xargs. Therefore, the shell does not replace it.

Then xargs executes ls, but it does not know about the aliases, so it just runs the first one it finds in the path.

The aliases are internal to the shell and there is no standardized way for a program to read them out.

marinus
  • 1,866
  • 13
  • 11