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 have a directory of .jpg files that continuously grows. I want to copy the most recent one elsewhere. This is what I currently have and it works, just curious if there's a better way to identify the most recent jpg file rather than using ls and tail.

#!/bin/bash
cd /home/pi/JPGS
fn=$(ls -rt1 | tail -1)
mv -f $fn /home/pi/WWW/webpic.jpg
share|improve this question
add comment

2 Answers

up vote 5 down vote accepted

There's a number of characters in file names that would make that fail. You can improve it with:

#! /bin/sh -
cd /home/pi/JPGS || exit
fn=$(ls -t | head -n1)
mv -f -- "$fn" /home/pi/WWW/webpic.jpg

Leaving a variable unquoted in list context (in shells other than zsh) is the split+glob operator, you almost never want to do that. -- marks the end of the options so "$fn" will not be taken as an option if it starts with -.

That still fails if filenames contain newline characters, but not space, tab, star, question mark, right square bracket, or start with dash.

Best is to use zsh here:

#! /bin/zsh -
mv -f /home/pi/JPGS/*.jpg(.om[1]) /home/pi/WWW/webpic.jpg

(.om[1]) are globbing qualifiers, they are a zsh specific feature. . restricts the glob to regular files (will not include symlinks, directories, devices...), om is to order on modification time, and [1] to only take the first file.

Note that if you want to assign that to a shell variable, that would have to be an array variable:

fn=(/home/pi/JPGS/*.jpg(.om[1]))

(not that it makes a lot of difference on how you use it later).

share|improve this answer
    
Thanks - I have a few questions: What's the significance of the -- and why is zsh preferable over bash here? I'm also not sure (.om[1]) does. –  Levon Dec 21 '13 at 21:57
1  
@Levon, answer updated with details. –  Stéphane Chazelas Dec 21 '13 at 22:21
    
Thanks .. good to store this away for future possible use, my filenames are quite regular so I won't have to worry about special cases for this. –  Levon Dec 22 '13 at 0:24
1  
@Levon, that's no reason (IMO) to use the wrong syntax. You should really get used to not writing things like mv $f xx which is the wrong syntax and bad practice (and where most of the shell-related vulnerabilities come from) but mv -- "$f" xx –  Stéphane Chazelas Dec 22 '13 at 13:58
    
You are right of course, my comment was with regard to the globing, not re -- which is clearly important from a security standpoint too - thanks again –  Levon Dec 22 '13 at 14:13
add comment

Listing file

You could reverse the logic on the ls a bit.

$ ls -t | head -n1

Details

   -t     sort by modification time, newest first

Now it shows up first so we can use head to return the first result.

NOTE: You could also sort the list by change time (ctime), though you're probably going to want to use modify time above - (mtime). The ctime is the last time the file status meta information was changed.

   -c     with -lt: sort by, and show, ctime (time of last modification of 
          file status information) with -l: show ctime and sort by name
          otherwise: sort by ctime, newest first

For example:

$ ls -tc | head -n1

Moving the file

To do the move more cleanly you'll want to wrap the filename in double quotes.

Example

$ mv -f -- "$fn" /home/pi/WWW/webpic.jpg

This will work in the majority of cases, there are a handful of legal filenames where it won't, for example, files with new lines. But these, though legal, are rarely ever intentionally used.

share|improve this answer
    
Thanks - I do know the filenames, so this won't be an issue. What is the advantage of using double-quotes around the variable? –  Levon Dec 21 '13 at 21:58
    
he'll probably want to sort on mtime (which reflects the modification time of the content of the file) rather than ctime (which reflects the modification time of metadata as well). –  Stéphane Chazelas Dec 21 '13 at 22:05
    
Note that, portably (and as the documentation you quote mentions), you need the -t option as well: ls -tc to sort on the inode-change time (and ls -lc to display the inode-change time, and ls -ut to sort on access time) –  Stéphane Chazelas Dec 21 '13 at 22:20
1  
@Levon - double quotes protects the mv command in cases where there are spaces within the file names. –  slm Dec 21 '13 at 22:57
1  
Thanks, very useful info re the use of "" .. my current filenames won't have that problem, but I will start using this as the default way of doing things. –  Levon Dec 22 '13 at 0:25
add comment

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.