Home > Net >  "find | xargs | ls" not running ls on filenames from find
"find | xargs | ls" not running ls on filenames from find

Time:11-15

So I have a directory with files and sub-directories in it. I want to get all the files recursively and then list them in long format, sorted by the modified date. Here's what I came up with.

find . -type f | xargs -d "\n" | ls -lt

However this only lists the files in the current directory and not the sub-directories. I don't understand why, given that the following prints out all the files.

find . -type f | xargs -d "\n" | cat

Any help appreciated.

CodePudding user response:

xargs can only start ls if it's passed ls as an argument. When you pipe from xargs into ls, only one copy of ls is started -- by the parent shell -- and it isn't given any of the filenames from find | xargs as arguments -- instead they're on its stdin, but ls never reads its stdin, so it doesn't even know that they're there.

Thus, you need to remove the | character:

# Does what you specified in the common case, but buggy; don't use this
# (filenames can contain newlines!)
# ...also, xargs -d is GNU-only
find . -type f | xargs -d '\n' ls -lt

...or, better:

# uses NUL separators, which cannot exist inside filenames
# also, while a non-POSIX extension, this is supported in both GNU and BSD xargs
find . -type f -print0 | xargs -0 ls -lt

...or, even better than that:

# no need for xargs at all here; find -exec can do the same thing
# -exec ... {}   is POSIX-mandated functionality since 2008
find . -type f -exec ls -lt {}  

Much of the content in this answer is also covered in the Actions, Complex Actions, and Actions in Bulk sections of Using Find, which is well worth reading.

  • Related