4

I want to move the last 3 modified files from a directory using bash commands. However, I noticed that I can use find in the following way:

find . -type f -mtime -0.5 -print -exec mv {} /home/user/Desktop \;

But I haven't figured out how to do the same with ls -tr | tail -n 3. For example, this doesn't work:

ls -tr | tail -n 3 -exec mv {} /home/user/Desktop             
tail: invalid option -- 'e'

The only reason I'd prefer to use the second option is in order to specify a number of files instead of an approximate time. Is it possible to make it work with ls and tail

Thanks!

2 Answers 2

6

The command you are looking for is xargs, as tail doesn't have a native ability to execute a program.

The full command would be:

ls -tr | tail -n 3 | xargs -I{} mv {} /home/user/Desktop

Breaking it down:

  • ls -tr lists files sorted by modification date/time (-t). The most recent are first, by default; it's reversed (most recently modified files last) if you add -r.
  • tail -n 3 filters it down to the last three entries.
  • xargs -I{} mv {} /home/user/Desktop runs mv {} /home/user/Desktop for each line received from tail. Note that the {} is replaced by the output from tail.

Note that you may need to escape the curly brackets in the call to xargs.

xargs -I\{\} mv \{\} /home/user/Desktop
2
  • Thanks. Actually, your suggestion was my first option but I wasn't too pleased with it because I didn't understand why I need to use the curly brackets next to -I. Do you know why?
    – r_31415
    Sep 10, 2014 at 5:55
  • You need to specify a placeholder. By default, xargs appends all arguments to the command. You need to insert each argument into a seperate command, in the middle. This requires the placeholder. Sep 10, 2014 at 6:42
1

Depending on the names on the files, a solution relying on the output of ls might be problematic. Using zsh, one could rely on globbing flags to get the job done:

mv *(.om[1,3]) ${somewhere}

The ‘magic’ is between the two parentheses after the *:

  • . only selects plain files;
  • om sorts the results of the glob by mtime;
  • [1,3] selects the first three results

I’m aware that the question specifically asks for a bash solution, so strictly speaking this answer won’t qualify. I’m posting it nonetheless for others who might have similar tasks and can use other shells.

1

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .