Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

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.)

share|improve this question
6  
Use find instead. –  Ignacio Vazquez-Abrams Sep 30 '12 at 17:14

4 Answers 4

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 {} .
share|improve this answer
    
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 –  sputnick 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'

edit

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 % .
share|improve this answer
    
Added explanations on find -printf options –  sputnick Sep 30 '12 at 20:39
    
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
    
Sure Francesco Turco, like said man cut, it prints till the end if there's more than one col. –  sputnick Oct 1 '12 at 11:17
    
POST edited to work with file-names with spaces. –  sputnick Oct 1 '12 at 11:42

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).

share|improve this answer

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.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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