LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Linux - Newbie (https://www.linuxquestions.org/questions/linux-newbie-8/)
-   -   Can ls take input from stdin? (https://www.linuxquestions.org/questions/linux-newbie-8/can-ls-take-input-from-stdin-889936/)

stf92 07-04-2011 10:03 PM

Can ls take input from stdin?
 
Hi:

I want to feed the output of locate to ls. Say
Code:

locate -r .*mp3$ | ls
But I've seen this has the same effect as
Code:

ls
I know there is a way, and a specific command. It's name is something like 'args'. I also know it's a fundamental command together with grep. There is a way, but I think is too complicated:
Code:

a1=$(locate granite)
ls -l $a1

Any idea?

Diantre 07-04-2011 10:07 PM

Code:

for i in "`locate -r .*mp3$`"; do ls "$i"; done
I'm sure someone will post an alternative using find/xargs.

divyashree 07-04-2011 10:33 PM

Yes Diantre..
Code:

find . -name "*.mp3" | xargs ls -l
or

Code:

find . -name "*.mp3" -exec ls -l {} \;
or
Code:

find . -name "*.mp3" -ls
Where . is the current directory ..

catkin 07-05-2011 12:28 AM

Quote:

Originally Posted by stf92 (Post 4405103)
There is a way, but I think is too complicated:
Code:

a1=$(locate granite)
ls -l $a1


Simpler: ls -l $( locate granite ) but. like the original, it breaks on file names that have spaces etc. in them.

David the H. 07-05-2011 12:35 AM

As above, but with a couple of caveats.

If the command you're using with -exec can take multiple arguments for input, then you can replace the final semicolon with a plus sign. This makes the command execute in only one (or as few as possible) processes, like xargs, whereas the semicolon executes the command once for each input,
Code:

find . -name "*.txt" -exec ls -l {} \+
When using xargs on input that could contain spaces or other reserved characters, you should use the null-separator for processing. Using -print0 in find will output the filenames delimited by nulls instead of newlines, and the -0 in xargs tells it to read the null-separated input.
Code:

find . -name "*.mp3" -print0 | xargs -0 ls -l
Without it, xargs will try to execute ls on individual parts of filenames, and you'll get "file not found" errors in return.

locate also has null-separator output ability, (using -0).
Code:

locate -0 -r ".*mp3" | xargs -0 ls -l

stf92 07-05-2011 02:36 AM

Quote:

Originally Posted by catkin (Post 4405204)
Simpler: ls -l $( locate granite ) but. like the original, it breaks on file names that have spaces etc. in them.

For this, a simple remedy: ls -l "$(locate granite)".

To everybody else: thanks, thanks a lot. Your posts are full of examples of the use of find, which has such a complex syntax and of xargs.

David the H. 07-05-2011 07:40 AM

Quote:

Originally Posted by stf92 (Post 4405332)
For this, a simple remedy: ls -l "$(locate granite)".

No, that doesn't work either, because then the entire output of locate is treated as a single word. The problem becomes the inverse of the non-quoted version. The only time this works correctly is if only a single file is found.

There's really no way to safely use simple command substitution when names can contain spaces. You need to be able to generate output in a way that treats each name as a separate entity, and to do that you need commands like find and xargs that allow control over the delimiting format, and/or loops of some kind (while+read in particular) to iterate over the entries.

See here:
http://mywiki.wooledge.org/Arguments
http://mywiki.wooledge.org/BashFAQ/020

Feel free to follow some of the links they provide for even more detail. ;)

MTK358 07-05-2011 07:44 AM

@stf92

Use this command (posted by David the H.), it's very simple, and it's impossible for any unusual characters in filenames to cause it to work wrong:

Code:

locate -0 -r ".*mp3" | xargs -0 ls -l

catkin 07-05-2011 08:06 AM

I'm confused. AIUI, Linux allows any character in pathname components except "/".

That means we can't simply take a list of pathnames generated by find and read it line by line because the names themselves may include line ends (C's "\n". ASCII's LF, 0x0A).

Happily find has the -print0 option which makes it list pathnames separated by null (C's "\0". ASCII's NUL, 0x00) and bash's read has the -r and -d options so we can specify null as a list separator by using -d '' because bash silently adds a null to the end of each string.

So far so good, but nulls are legitimate path component characters so the paths themselves could contain nulls which read -r -d '' would treat as list separators. :scratch:

David the H. 07-05-2011 08:37 AM

Null is illegal in filenames according to the posix specification, along with the backslash.

http://pubs.opengroup.org/onlinepubs...tml#tag_03_170

And while some filesystems will accept null-bytes (and/or slashes) in names, none of the common Linux ones like ext2/3/4 do.

http://en.wikipedia.org/wiki/Comparison_of_file_systems

In addition, the bash shell (and pretty much all shells, probably) doesn't allow null bytes inside of strings, which is why it can safely be used as a delimiter. See the page on "arguments" I gave above.


All times are GMT -5. The time now is 11:38 PM.