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

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.