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.)