unix command to find most recent directory created
Solution 1
This is the answer to the question I think you are asking.
When I deal with many directories that have date/time stamps in the name, I always take the approach that you have which is YYYYMMDD - the great thing about that is that the date order is then also the alphabetical order. In most shells (certainly in bash and I am 90% sure of the others), the '*' expansion is done alphabetically, and by default 'ls' return alphabetical order. Hence
ls | head -1
ls | tail -1
Give you the earliest and the latest dates in the directory.
This can be extended to only keep the last 5 entries etc.
Solution 2
lastdir=`ls -tr <parentdir> | tail -1`
I don't know how to make the backticks play nice with the commenting system here. Just replace those apostrophes with backticks.
Solution 3
The trouble with the ls based solutions is that they are not filtering just for directories. I think this:
cp `find . -mindepth 1 -maxdepth 1 -type d -exec stat -c "%Y %n" {} \; |sort -n -r |head -1 |awk '{print $2}'`/* /target-directory/.
might do the trick, though note that that will only copy files in the immediate directory. If you want a more general answer for copying anything below your newest directory over to a new directory I think you would be better off using rsync like:
rsync -av `find . -mindepth 1 -maxdepth 1 -type d -exec stat -c "%Y %n" {} \; |sort -n -r |head -1 |awk '{print $2}'`/ /target-directory/
but it depends a bit which behaviour you want. The explanation of the stuff in the backticks is:
.
- the current directory (you may want to specify an absolute path here)-mindepth/-maxdepth
- restrict the find command only to the immediate children of the current directory-type d
- only directories-exec stat ..
- outputs the modified time and the name of the directory from findsort -n -r |head -1 | awk '{print $2}'
- date orders the directory and outputs the name of the most recently modified
Solution 4
After some experimenting, I came up with the following:
The unix stat command is useful here. The '-t' option causes stat to print its output in terse mode (all in one line), and the 13th element of that terse output is the unix timestamp (seconds since epoch) for the last-modified time. This command will list all directories (and sub-directories) in order from newest-modified to oldest-modified:
find -type d -exec stat -t {} \; | sort -r -n -k 13,13
Hopefully the "terse" mode of stat will remain consistent in future releases of stat !
Here's some explanation of the command-line options used:
find -type d # only find directories
find -exec [command] {} \; # execute given command against each *found* file.
sort -r # reverse the sort
sort -n # numeric sort (100 should not appear before 2!)
sort -k M,N # only sort the line using elements M through N.
Returning to your original request, to copy files, maybe try the following. To output just a single directory (the most recent), append this to the command (notice the initial pipe), and feed it all into your 'cp' command with backticks.
| head --lines=1 | sed 's/\ .*$//'
Solution 5
If your directories are named YYYYMMDD
like your question suggests, take advantage of the alphabetic globbing.
Put all directories in an array, and then pick the first one:
dirs=(*/); first_dir="$dirs";
(This is actually a shortcut for first_dir="${dirs[0]}";
.)
Similarly, for the last one:
dirs=(*/); last_dir="${dirs[$((${#dirs[@]} - 1))]}";
Ugly syntax, but this is what it breaks down to:
# Create an array of all directories inside the working directory.
dirs=(*/);
# Get the number of entries in the array.
num_dirs=${#dirs[@]};
# Calculate the index of the last entry.
last_index=$(($num_dirs - 1));
# Get the value at the last index.
last_dir="${dirs[$last_index]}";
I know this is an old question with an accepted answer, but I think this method is preferable as it does everything in Bash. No reason to spawn extra processes, let alone parse the output of ls
. (Which, admittedly, should be fine in this particular case of YYYYMMDD
names.)
Related videos on Youtube
jdamae
Updated on June 09, 2020Comments
-
jdamae almost 4 years
I want to copy the files from the most recent directory created. How would I do so in unix?
For example, if I have the directories names as date stamp as such:
/20110311 /20110318 /20110325
-
Tom Zych about 13 yearsIn bash you can use $(...) instead of backticks.
-
jdamae about 13 yearsthat's basically what i need. Thanks!
-
jdamae about 13 yearsthanks for your suggestions. Very interesting. Can you edit this so I can see the entire command? I'm not sure if i'm trying this correctly. thanks again.
-
jdamae about 13 yearsActually, this would work well for me in the case that I do need the top 2-3 latest dirs created.
ls | tail -2
-
janmoesen over 11 yearssupertrue: not in Bash, or at least not that I am aware of. Were you trying it in the plain old Bourne shell
sh
? -
supertrue over 11 yearsNo, I use Bash (Mac Terminal), I was just wondering what the meaning of it was, given that # is also used for comments.
-
janmoesen over 11 yearsAh, I see. It has special meaning when it's inside a variables with braces.
${#foo}
counts the number of characters in a normal (string) variable calledfoo
, and${foo[@]}
counts the number of elements in an array calledfoo
. See Bash parameter expansion.