Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I was wondering if anyone knows how to change the timestamps of folders recursively based on the latest timestamp found of the files in that folder.

So for example:

jon@UbuntuPanther:/media/media/MP3s/Foo Fighters/(1997-05-20) The Colour and The Shape$ ls -alF
total 55220
drwxr-xr-x  2 jon jon    4096 2010-08-30 12:34 ./
drwxr-xr-x 11 jon jon    4096 2010-08-30 12:34 ../
-rw-r--r--  1 jon jon 1694044 2010-04-18 00:51 Foo Fighters - Doll.mp3
-rw-r--r--  1 jon jon 3151170 2010-04-18 00:51 Foo Fighters - Enough Space.mp3
-rw-r--r--  1 jon jon 5004289 2010-04-18 00:52 Foo Fighters - Everlong.mp3
-rw-r--r--  1 jon jon 5803125 2010-04-18 00:51 Foo Fighters - February Stars.mp3
-rw-r--r--  1 jon jon 4994903 2010-04-18 00:51 Foo Fighters - Hey, Johnny Park!.mp3
-rw-r--r--  1 jon jon 4649556 2010-04-18 00:52 Foo Fighters - Monkey Wrench.mp3
-rw-r--r--  1 jon jon 5216923 2010-04-18 00:51 Foo Fighters - My Hero.mp3
-rw-r--r--  1 jon jon 4294291 2010-04-18 00:52 Foo Fighters - My Poor Brain.mp3
-rw-r--r--  1 jon jon 6778011 2010-04-18 00:52 Foo Fighters - New Way Home.mp3
-rw-r--r--  1 jon jon 2956287 2010-04-18 00:51 Foo Fighters - See You.mp3
-rw-r--r--  1 jon jon 2730072 2010-04-18 00:51 Foo Fighters - Up in Arms.mp3
-rw-r--r--  1 jon jon 6086821 2010-04-18 00:51 Foo Fighters - Walking After You.mp3
-rw-r--r--  1 jon jon 3033660 2010-04-18 00:52 Foo Fighters - Wind Up.mp3

The folder "(1997-05-20) The Colour and The Shape" would have its timestamp set to 2010-04-18 00:52.

share|improve this question
up vote 13 down vote accepted

You can use touch -r to use another file's timestamp instead of the current time (or touch --reference=FILE)

Here are two solutions. In each solution, the first command changes the modification time of the directory to that of the newest file immediately under it, and the second command looks at the whole directory tree recursively. Change to the directory (cd '.../(1997-05-20) The Colour and The Shape') before running any of the commands.

In zsh (remove the D to ignore dot files):

touch -r *(Dom[1]) .
touch -r **/*(Dom[1]) .

On Linux (or more generally with GNU find):

touch -r "$(find -mindepth 1 -maxdepth 1 -printf '%T+=%p\n' |
            sort |tail -n 1 | cut -d= -f2-)" .
touch -r "$(find -mindepth 1 -printf '%T+=%p\n' |
            sort |tail -n 1 | cut -d= -f2-)" .

However note that those ones assume no newline characters in file names.

share|improve this answer
The commands work (I used the Linux ones) but it's not working recursively. I ran it in my root folder (/media/media/MP3s) and no such luck with the rest of the artist directories in there. Thank you for your help so far. – MonkeyWrench32 Sep 3 '10 at 1:01
@MonkeyWrench32: I answered your question as I understood it. Do you want to apply the command to every directory underneath /media/media/MP3s? Then in zsh: for d in /media/media/MP3s/**/*(/); do touch -r $d/*(Dom[1]) $d; done. Without zsh (but really, use zsh, it's just simpler): put the command in a script and run find /media/media/MP3s -type d -execdir /path/to/the/script \;. – Gilles Sep 3 '10 at 7:10
Perfection! You are a zsh master! :D – MonkeyWrench32 Sep 3 '10 at 15:30
If you use for d in ... how can you adapt the following, so it will also work with folders, that contain spaces? (that is still missing in my solution) – rubo77 Aug 16 '13 at 11:36
@rubo77 I don't understand what you're talking about. All the solutions I posted work on file names containing spaces (some of them fail on file names containing newlines). Note that some of my solutions require zsh, which doesn't require double quotes around variable substitutions. – Gilles Aug 16 '13 at 12:16

That's not "recursively", it's just changing all the timestamps in a folder. If that's what you mean, there's two steps.

stat -c '%Y' filename will output the timestamp of filename, and stat -c '%Y %n' * will output the timestamp and filename of every file in the folder, so this will find the filename of the most recently modified file in the current folder:

mostrecent="`stat -c '%Y %n' * | sort -n | tail -n1 | cut -d ' ' -f '2-'`"

On second thought, there's a way easier way to get the highest timestamp in the folder:

mostrecent="`ls -t | head -n1`"

Then you want to change all the files in the folder to have the same timestamp as that file. touch -r foo bar will change bar to have the same modified timestamp as foo, so this will change all the files in the folder to have the same modified timestamp as your most recently modified file:

touch -r "$mostrecent" *

So, the one-liner is:

touch -r "`ls -t | head -n1`" *
share|improve this answer
Parsing the output of ls is a bad idea, though I admit it's a tempting case. It's still risky if ls mangles file names containing non-ASCII characters. If you want one-liners, use zsh:-) – Gilles Sep 2 '10 at 21:42
@Gilles It is, but I've yet to run into a problem doing it; I suppose because my filenames don't contain non-ASCII characters. Your answer is better though – Michael Mrozek Sep 2 '10 at 21:45

I put the work together and now:

This would be a script that changes all directories inside /tmp/test/ to the timestamp of the newest file inside each directory:

if [ -z "$1" ] ; then
  echo 'ERROR: Parameter missing. specify the folder!'
#MODE=tail # change to newest file
MODE=head # change to oldest file
for d in "$1"/*/; do
  echo "running on $d"
  find "$d" -type d -execdir \
    echo touch --reference="$(find "$d" -mindepth 1 -maxdepth 1 -printf '%T+=%p\n' \
                              | sort | "$MODE" -n 1 | cut -d= -f2-)" "$d" \;
    # remove echo to really run it

you can add some testing files in /tmp like this:

mkdir /tmp/test
cd /tmp/test
mkdir d1
mkdir d2
touch d1/text1.txt
sleep 1
touch d1/movie1.mov
touch d2/movie2.mov
sleep 1
touch d2/text2.txt
touch notthis.file
share|improve this answer
thanks for your edit, it works! although the echo does remove the " again, it first looks, like it is missing, but it works. – rubo77 Aug 16 '13 at 20:51

I didn't really like the obscurity of the shell commands and quickly did it in python.

It recursively sets all directory mtimes to the newest non-excluded file/dir mtime inside.

import os
import sys

EXCLUDE_DIRS = ['.git', '.hg']

def inheritMTime(path):
    for root, dirs, files in os.walk(path, topdown=False, followlinks=False):
        currentMaxMtime = None
        for subpath in files:
            if subpath in EXCLUDE_FILES:
                print "ignore file", os.path.join(root, subpath)
            currentMaxMtime = max(currentMaxMtime, os.lstat(os.path.join(root, subpath)).st_mtime)
        for subpath in dirs:
            if subpath in EXCLUDE_DIRS:
                print "ignore dir", os.path.join(root, subpath)
            currentMaxMtime = max(currentMaxMtime, os.lstat(os.path.join(root, subpath)).st_mtime)
        if currentMaxMtime is not None:
            os.utime(root, (currentMaxMtime, currentMaxMtime))

if __name__ == "__main__":
    for dir in os.listdir(sys.argv[1]):
        if os.path.isdir(dir):
            current = os.path.join(sys.argv[1], dir)
share|improve this answer

Your Answer


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.