I'd like to do something like this to move the last two downloaded files:

mv ` ls -rt ~/Downloads/ | tail -2 ` .

Unfortunately, ls only gives the filenames. How can I adapt the code above?

(Before someone points it out, I'm aware of the problems in piping the output of ls. I'd only use this when I know the filenames in question.)


Okay, so if you won't give up on ls, then at least try to get out of the habit of using backticks for everything, especially when xargs is a better fit:

ls -rtd ~/Downloads/* | tail -n2 | xargs -I{} mv {} .
  • Your xargs pleases me more than the backticks. But is there any technical reason to prefer this sequence of pipes and xargs over the usage of backticks or is this only a matter of taste? – miracle173 Sep 30 '12 at 19:00
  • In this case we're only looking at two files, but if we wanted to move thousands of files, we might accidentally try to create a command line that was too long. – geocar Sep 30 '12 at 19:12
  • Also: In the case of mere hundreds of files, we can start work immediately. With backticks, we have to wait until the entire subcommand is finished. – geocar Sep 30 '12 at 19:13
  • Also: When you manage to kick the habit of using ls, you can take advantage of xargs -0 – geocar Sep 30 '12 at 19:15
  • 3
    Parsing ls is discouraged : mywiki.wooledge.org/ParsingLs – Gilles Quenot Sep 30 '12 at 21:54

You can use GNU find there :

mv $(find ~/Download -mindepth 1 -maxdepth 1 -printf '%Ts %p\n' | sort -n | cut -d ' ' -f2- | tail -n 2) .

The find -printf options :

  • %Ts to display the time as epoch
  • %p the file path

See man find | less +/'^ *-printf'


if you need to deal with spaces in file-names, I recommend this another solution :

find -maxdepth 1 -printf '%Ts %p\n' |
    sort -n |
    cut -d ' ' -f2- |
    tail -n 2 |
    xargs -i% mv % .
  • Added explanations on find -printf options – Gilles Quenot Sep 30 '12 at 20:39
  • 1
    I'm curious: is there any particular reason to use -f2- instead of -f2 as an option to cut? What's the second dash for? – Francesco Turco Oct 1 '12 at 7:52
  • 1
    Sure Francesco Turco, like said man cut, it prints till the end if there's more than one col. – Gilles Quenot Oct 1 '12 at 11:17
  • POST edited to work with file-names with spaces. – Gilles Quenot Oct 1 '12 at 11:42

Use ls -rt ~/Downloads/*instead of ls -rt ~/Downloads/. In ls -rt ~/Downloads/* the argument string is first expanded by the shell (this is called filename globbing). So you get a list of paths as arguments for the ls -rt command, which then sorts it in the way you specify by the options of ls. In contrast, the command ls -rt ~/Downloads/ reads the content of the directory ~/Downloads/. This is a list of files without the directory path.


With zsh:

mv ~/Downloads/*(.om[1,2]) .

The (...) part are called globbing qualifiers, one of the killer features of zsh. Each qualifier (usually single characters) allows to filter the matched entries based on attributes of the files (type, size, time...), alter the order in which they are expanded, or modify how they are expanded.

Above, we've got:

  • . (dot): select regular files only (not directories, symlinks...)
  • om: order the list by modification time.
  • [1,2]: select only the first two entries.

Also note that the command will fail if there's no match (where other shells could accidentally move the wrong file/dir).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.