Piping the contents of a file to ls

You are looking for the xargs (transpose arguments) command.

xargs ls < input.txt

You say you want /bin to be the "input" to ls, but that's not correct; ls doesn't do anything with its input. Instead, you want /bin to be passed as a command-line argument to ls, as if you had typed ls /bin.

Input and arguments are completely different things; feeding text to a command as input is not the same as supplying that text as an argument. The difference can be blurred by the fact that many commands, such as cat, will operate on either their input or their arguments (or both) – but even there, we find an important distinction: what they actually operate on is the content of files whose names are passed as arguments.

The xargs command was specifically designed to transform between those two things: it interprets its input as a whitespace-separated list of command-line arguments to pass to some other command. That other command is supplied to xargs as its command-line argument(s), in this case ls.

Thanks to the input redirection provided by the shell via <, the arguments xargs supplies to ls here come from the input.txt file.

There are other ways of accomplishing the same thing; for instance, as long as input.txt does not have so many files in it that they won't fit in a single command line, you can just do this:

ls $(< input.txt)

Both the above command and the xargs version will treat any spaces in the input.txt file as separating filenames, so if you have filenames containing space characters, you'll have to do more work to interpret the file properly. Also, note that if any of the filenames contain wildcard/"glob" characters like ? or * or [...], the $(<...) version will expand them as wildcard patterns, while xargs will not.


ls takes the filenames from its command line, not its standard input, which | ls and ls < file would use.

If you have only one file listed in input.txt and the filename doesn't contain trailing newlines, it's enough to use (note quotes):

ls "$(cat input.txt)"

Or in almost all but plain POSIX shell:

ls "$(< input.txt)"

If there are many filenames in the file, you'd want to use xargs, but to deal with whitespace in the names, use -d "\n" (with GNU xargs) to take each line as a filename.

xargs -d "\n" ls < input.txt

Or, if you need to handle filenames with newlines, you can separate them using NUL bytes in the input, and use

xargs -0 ls < input.txt

(This also works even if there's only one filename.)

Tags:

Bash