How to copy the two most recently added files to another directory - HP-UX?

Hello,

I am attempting to find and copy the two most recently added files to a specific directory, that fit a specific format.

I was able to find the command to list the two most recently added files in directory:

ls -1t | head -n 2

The command lists the two files names in a vertical list, top being most recent.

Q1: How can I extend this command to only select the most recent files with a specific format?

Q2: How can I copy over the files to a new directory once the proper files are chosen?

Format: 'OUS_*_*_*.html'

Attempt:

# Does not select two most recent files
find . -type f $fileNameFormat -exec cp -pf {} $testDestDir \;

Well, you almost have it. Your logic just needs to extend and think "I can get the names of the files, now I need to copy each on in turn to the target area." This is repeating a process in a loop. There are several ways to code this:-

for file in `ls -1t | head -n 2`
do
   cp $file target_direcotry
done
ls -1t | head -n 2 | while read file
do
   cp $file target_directory
done

Do either of these help?

You might get away with a one-line command:-

cp `ls -1t | head -n 2` target_directory

For the second part, if you need to specify a file pattern, use it as an arguement to the ls command in whichever structure above helps. That part would then become:-

.... ls -1t OUS_*_*_*.html | head -n 2 ......

Let us know how you get on.

Robin

1 Like

This is exactly what I am looking for, thanks Robin. This is my first script so I have yet to get down the proper syntax for control structures and variable handling.

I am having an issue while testing the given code:

# Select two most recent files with corresponding file name format and 
# copy to destination directory

for file in 'ls -1t OUS_*_*_*.txt | head -n 2'
do 
	cp "$file" $testDestDir
done

I am getting this error:

cp: cannot access ls -1t OUS_*_*_*.txt | head -n 2: No such file or directory

Do you know why I am getting this error?

Edit: When removing the quotation marks from $file I get the following errors:

cp: cannot access ls: No such file or directory
cp: cannot access -1t: No such file or directory
cp: cannot access |: No such file or directory
cp: cannot access head: No such file or directory
cp: cannot access -n: No such file or directory
cp: cannot access 2: No such file or directory

rbatte1 was using backticks ` whilst you replaced those with the apostrophe (or single quote) ' . The meaning of both is remarkable different - the former introduces command substitution, the latter introduces, say, "constants" (text that is not expanded by the shell).
Please be aware that backticks are deprecated, use $(...) instead.
All of above you'll find in man bash (or whatever shell you are using).

1 Like

Hello mattkoz,

Could you please try following command, it may help you.

ls -1t OUS_*_*_*.txt | awk 'NR==1||NR==2{print "cp " $NF " path_to_directory"}'

Above command will only print the command as follows.

cp OUS_123112343567_wertc_1234.txt path_to_directory
cp OUS_123123~4467543_wertc_1234.txt path_to_directory

If happy with results then you can use following command.

ls -1t OUS_*_*_*.txt | awk 'NR==1||NR==2{print "cp " $NF " path_to_directory"}' | sh

NOTE: I have just shown an example of files.

Thanks,
R. Singh

Thank you, you are exactly right. Did not use backtick. I have another somewhat related question.

I am attempting to cycle through files in a directory in order to mail them to a email one at a time. The filenames have spaces however and I get a similar error to the previous one I listed, involving the backticks. What I assume is happening is that the spaces are being interpreted as spaces between multiple file names rather than the spaces within the filename.

for file in `ls -1t OUS*.htm* | head -n 2`
do
	(echo "Body of text 4"; uuencode `$file`) | mailx -m -s "Test" $testEmail
done

Errors:

/home/koczmj/OutageReportScript.ksh[61]: OUS:  not found
/home/koczmj/OutageReportScript.ksh[61]: Complete:  not found
/home/koczmj/OutageReportScript.ksh[61]: Scheduled:  not found
/home/koczmj/OutageReportScript.ksh[61]: Job:  not found
/home/koczmj/OutageReportScript.ksh[61]: List.htm:  not found
/home/koczmj/OutageReportScript.ksh[61]: OUS:  not found
/home/koczmj/OutageReportScript.ksh[61]: Scheduled:  not found
/home/koczmj/OutageReportScript.ksh[61]: Job:  not found
/home/koczmj/OutageReportScript.ksh[61]: List:  not found
/home/koczmj/OutageReportScript.ksh[61]: Filtered:  not found
/home/koczmj/OutageReportScript.ksh[61]: by:  not found
/home/koczmj/OutageReportScript.ksh[61]: Criteria.htm:  not found

How can I properly format my code so the spaces within the filenames are read correctly?

The filenames should be:
OUS Complete Scheduled Job List.htm
OUS Scheduled Job List Filtered by Criteria

Thanks!

Look carefully at rbatte1's post #2 and try

ls -1t "OUS*.htm*" | head -n 2 | while read file
do
   cp $file target_directory  ( ... or whatever you want to do with it ... )
done

And, don't use backticks around $file - they're NOT the panacea!

I am gettting this error now:

"OUS*.htm*" not found

I have checked the directory and there are files fitting that format. Should I use something other than quotation marks?

Sorry, you're right; just drop the double quotes...

I apologize for all the questions, but this is still giving me trouble. I removed the quotation marks, but it is still not handling the spaces within the file name correctly.

ls -1t OUS*.htm* | head -n 2 | while read file
do
	uuencode $file $file | mailx -m -s "Working" $testEmail
done	

Errors:

OUS: No such file or directory
Null message body; hope that's ok
OUS: No such file or directory
Null message body; hope that's ok

Different attempt:

IFSSAVE=$IFS
IFS=$'\n'

for file in `ls -1t OUS*.htm* | head -n 2`
do
	uuencode $file $file | mailx -m -s "New" $testEmail
done

IFS=$IFSSAVE

Errors:

OUS Complete Scheduled Job List.htm
OUS Scheduled Job List Filtered by Criteria.htm: No such file or directory
Null message body; hope that's ok

Any thoughts?

Ah, the fun of quotes!

You need to wrap variables in double quotes " then the shell will interpret the value but use it as a single string. Code it like this:-

uuencode "$file" "$file" | .......

It's annoying to get used to, but it will soon become natural.

I hope that this helps,
Robin

Please post the result of ls -1t OUS*.htm* alone and of ls -1t OUS*.htm* | head -n 2