1

Would there be a way to use the output of ls -ltr with xargs?

Assume that the result of ls is one file as below.

ls -ltr | tail -1 | xargs -I{} open {}

For comparison, I use the following command to use find to move files:

find ~/Downloads/ -iname '*hello*' -print0 | xargs -0 -I{} mv {} ./

Can we somehow use NUL character?


[Solved]
As mentioned in the @illkachu's comments, the following works but is not suggested.

somecmd "$(ls -tr | tail -1)"

What Stéphane suggests seem be alternatives.

2 Answers2

2

Generally, you wouldn't as the output of ls is not post-processable reliably.

For instance:

open -- "$(ls -t | head -n 1)"

doesn't work if the name of newest file contains newline characters.

Ideally, you'd want:

ls -zt | head -zn1 | xargs -r0 open --

But unfortunately, I don't know of any ls implementation that supports a -z/-0 option, and the maintainers of GNU ls at least declined several times to add it.

Now, there are other ways with some implementations.

With the GNU and ast-open implementations of ls, in the C locale, the output with the --quoting-style=shell-always option is post-processable by zsh, ksh93 or bash:

export LC_ALL=C
eval "files=($(ls --quoting-style=shell-always -t))"

open -- "${files[0]}" # $files[1] with zsh

Though in zsh, you'd just do

open ./*(om[1])

or:

open ./Ctrl+Xm

as zsh has built-in support to sort files by modification time (and many other criteria that go far beyond ls capabilities).

FreeBSD ls has a --libxo option to generate json or xml output, so you could do:

ls --libxo=json -t | perl -MJSON::PP -0777 -l0 -ne '
  print decode_json($_)
    ->{"file-information"}
    ->{directory}->[0]
    ->{entry}->[0]
    ->{name}' | xargs -r0 open --

But then it would be simpler to do the whole thing in perl.

1

As you already have been told: In general this is not the approach you want to chose. However, as a start:

ls -ltr | awk '/^-/ { print $9; }' | xargs
Hauke Laging
  • 90,279