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.