Yes, with -0, xargs expects a NUL-delimited list on stdin. Here, you're feeding it the part of the name of the newest file after the last newline characters in it, followed by a newline character (that newline character is added by ls and not part of file name).
There is no NUL in that input, so xargs takes the whole input as one argument to pass to mv which does contain that newline character, so it would only work correctly if the name of newest file did contain one and only one newline character and it was the last character in the file name.
Here, you'd need to make sure ls outputs a NUL-delimited list instead of a newline-delimited one, but I'm not aware of any ls implementation that can.
Or you'd need to revert to the default xargs input format (without -0) where arguments are delimited by blanks (the list of which depends on the xargs implementation and possibly the locale) or newlines and where "..." and '...' and \ are used for escaping those and each other (in a different way from the same shell quoting operators). As some xargs implementations try to interpret their input as text but filenames can contain any byte values (other than NUL and /), you'll also need to do that processing in the C locale.
export LC_ALL=C
ls -td ./* | awk -v q="'" '
{gsub(/"/, "\"\\\"\"")} # escape "
NR == 1 {printf "\"%s", $0; next}
/\// {exit} # a / means the start of the second file
{printf "\"\\\n\"%s", $0} # escape newlines
END {if (NR) print "\""}' |
xargs -J % mv % newname
As you can see, using xargs reliably is a total pain. Some xargs implementations also have a very low limit on the size of argument or input lines. Note that -J is a non-portable BSD extension.
Dealing with arbitrary file names using line-based utilities like ls is also very hard.
Best would be to use zsh which can sort the list of files by modification times by itself as @Kusalananda has shown:
mv -- *(.om[1]) newname
In bash, you could also do:
IFS= read -rd / newest < <(ls -td ./*) && newest=${newest%.}
newest=${newest%?} # strip newline
[ -n "$newest" ] && mv "$newest" newname
(would also work in ksh93 or zsh). Like in the previous xargs approach, we're using ./* to be able to tell on which line the second file in the list starts.
lsis discouraged. – AdminBee Jun 22 '20 at 15:22finda better bet? – Scott Anderson Jun 22 '20 at 15:23