Question

The problem I faced with is that wildcard quantificator doesn't pass through xargs to command for some reason.

Assume, that we have file file1 with such content:

-l
-a
f*

we need to pass arguments to ls via xargs.

cat file1 | xargs -n3 ls

The output equivalent to ls -la command, with additon from terminal, that

ls: cannot access f*: No such file or directory.

But the file is in directory (ls -la f* returns suitable output) If we substitute f* to file1 for example, we'll have right output too.

Can you explain me, why does it happen? Thanks.

EDIT1:

It seems interesting to add, how we can pass arguments from file file1 through shell interpreter to ls command. Below is the example:

ls `xargs -n3 < file1`

Now shell expansion is made before ls invocation resulting in same output as for ls -la f*

Was it helpful?

Solution

The f* expression is also known as a shell glob, and is supposed to be interpreted by the shell. You can try it out independently e.g. by running echo f*.

When you run ls -la f* from the shell, the shell interprets it according to your directory contents, and calls ls with the expanded version, like: ls -la file1 file2 file3. You can get some commands confused about this if it matches no file and the command expects one.

But when you pass that argument to ls through xargs, the shell doesn't get a chance to expand it, and ls feels like it's invoked exactly as ls -la f*. It recognizes -la as options, and f* as a filename to list. That file happens not to exist, so it fails with the error message you see.

You could get it to fail on a more usual filename:

$ ls non_existing_file
ls: cannot access non_existing_file: No such file or directory.

Or you could get it to succeed by actually having a file of that name:

$ touch 'f*'
$ xargs ls -la <<< 'f*'
-rw-rw-r-- 1 jb jb 0 2013-11-13 23:08 f*
$ rm 'f*'

Notice how I had to use single quotes so that the shell would not interpret f* as a glob when creating and deleting it.

Unfortuately, you can't get it to expand it when it gets passed directly from xargs to ls, since there's no shell there.

OTHER TIPS

The contents of file are passed to xargs via standard input, so the shell never sees them to process the glob. xargs then passes them to ls, again without the shell ever seeing them, so f* is treated as a literal 2-character file name.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top