Files and directories have a number of attributes.
Modification time can be an issue when looking for the 'latest' directory. I wrote a shell script that was creating new directories and also writing files into the latest directory depending on the switches past in. I found if I started the two processes at exactly the same time. The oldest directory was modified last, completely stuffing up my sort later looking for the newest directory.
find . -name "partname*" -maxdepth 1 -printf '%T@ %p\0' 2>/dev/null | sort -z -nr
find
-name I only want certain files or directories
-maxdepth 1 only look at this level not recursively
-printf
%T modification time
@ seconds since Jan. 1, 1970, 00:00 GMT
%p file name
\0 the terminator rather than \n (newline) to avoid problems with
strange filenames
2>/dev/null don't include errors in the output
| (pipe) then do the next command I give you
sort
-z because I used \0 in the previous command don't look for a linefeed
-n sort numerically
-r put the largest number at the top
But modification time was an issue so I shifted to
ctime - which is change time (not creation)
change time –ctime %C
modify time –mtime %T
(access time –atime %A )
Change time is set on creation and alters when there is a chmod, chown or mv on the file.
find . -name "partname*" -maxdepth 1 -printf '%C@ %p\0'
2>/dev/null | sort -z -nr
So in order to scrape off the latest file system name this completes in my scripts with:
IFS= read -r -d $'\0' line < < (find . -name "partname*" -maxdepth 1 -printf '%C@ %p\0' 2>/dev/null | sort -z -nr )
FullPathToNewestDirectory="${line#* }"
IFS Internal Field Separator - make this the delimiter
read
${line#* } the space after * matters here
${parameter#word the pattern word will be removed from the beginning of the value of $parameter. It's called "Remove Smallest Prefix Pattern" because it will remove the shortest matching prefix string that matches the pattern in word (with ## in place of # it removes the longest matching prefix string).
< < Note the space between these two redirect symbols
So now I have a variable that looks like
/dir/dir/dir (I'm looking for a list of directories, yours might be /dir/dir/file it's all the same)
and I only want the last part of this path
echo $FullPathToNewestDirectory | awk -F/ '{ print $(NF ) }'
echo show contents of the variable
| (pipe) then do the next command I give you
awk
-F/ the fields separator is / (the lack of space between F and / is important)
'{ print $(NF ) }' NF is number of fields of the current record, printing $NF means printing the last one.
I use NF because I'm not always sure server to server how many levels of directories I might have:
IFS= read -r -d $'\0' line < < (find $BACKUPHOME -name "backupdir_partname*" -maxdepth 1 -printf '%C@ %p\0' 2>/dev/null | sort -z -nr )
FullPathToNewestDirectory="${line#* }"
ActualDirectory=`echo $FullPathToNewestDirectory | awk -F/ '{ print $(NF ) }'`
If you plan to work with this in a script you need to consider that if there are no files or directories where you are looking you will end up with an empty (but set) variable, this might mess up anything coming later. You need to be sure you handle that/
I found it important to test for
-z ${FullPathToNewestDirectory:+x}
This tests that not only is the
parameter set but also that it isn't null.
As I've been writing this I've been trying to recall what prevented me from using
ls to get where I needed to be. I know It caught me out and why may come back to me. If it does, I will update again but why not see if it take you where
you need to go first
Read more...