LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (http://www.linuxquestions.org/questions/programming-9/)
-   -   Bash Script to Copy Modification Date from a file to his folder (http://www.linuxquestions.org/questions/programming-9/bash-script-to-copy-modification-date-from-a-file-to-his-folder-894503/)

pjgm 07-29-2011 01:14 PM

[SOLVED] Bash Script to Copy Modification Date from a file to his folder
 
Hi There,

I need this script but I don't know how to do it :(

I have one folder with several folders inside.

On each folder a have one MKV or AVI file inside...

What I need is a script to change the "modification date" of each folder to the "modification date" of each MKV or AVI that the folder has inside.

Cheers
PJGM

PS: My system: NAS with Linux 2.6.24.4

colucix 07-29-2011 01:35 PM

Code:

while read file
do
  touch -t $(date -r "$file" +%Y%m%d%H%M) "$(dirname "$file")"
done < <(find . \( -iname \*.avi -o -iname \*.mkv \))


MensaWater 07-29-2011 01:36 PM

You can use the "touch" command to change dates including modifications dates (-m option to change only modification date).

Type "man touch" for more detail on the touch command.

Generally doing "touch -m CCYYMMDD <filename>" would do what you want for the filename (including a directory filename).
e.g.
touch -m 20110630 testdir
Would put the date Jun 30 2011 on the directory named testir.

touch -m 20060512 test.avi
Would put the date May 12 2006 on the file test.avi.

You can use the "ls -l -time-style +%Y%m%d <filename>" to list a file with its date in the same format as above. (Type "man ls" for more detail on the ls command.

You'd want to do a for loop to do what you're asking (or what I think you're asking). Something like:
Code:

cd <mainfolder>
for folder in $(ls -d *)
do touchtm=$(ls -l -time-style +%Y%m%d $folder/* |awk '{print $6}')
  touch $touchtm $folder
done

You'd substitute your parent folder for what I show as <mainfolder> above. Note the above scripts assumes there is only one file in each of your subdirectories. You'd have to figure out a file specification if there were more (e.g. if you had dozens of files but only one file with a .avi suffix in each directory you could use "*.avi).

The awk command above just gets the 6th position from the ls output and that is the position that has the date of the file. (You can type "man awk" for more detail - awk is a full text/programming utility so it is often best to find a good tutorial for it for more advanced usage - there are many on the internet.)

Prior to trying this in your real directory you might want to make a test directory as your main folder then copy a couple of the subdirectories and their contents to it to be sure the loop works the way you want.

Diantre 07-29-2011 01:44 PM

Well, here's another one: ;)

Code:

#!/bin/bash

for i in *; do
    if [[ -d $i ]]; then
        moddate=$(stat -c %y "$i")
        touch -m -c -d "$moddate" "$i/*.mkv" "$i/*.avi"
    fi
done

Run it from the main directory with subdirs containing videos.

colucix 07-29-2011 01:55 PM

Quote:

Originally Posted by Diantre (Post 4428676)
Well, here's another one: ;)

Code:

#!/bin/bash

for i in *; do
    if [[ -d $i ]]; then
        moddate=$(stat -c %y $i)
        touch -m -c -d "$moddate" $i/*.mkv $i/*.avi
    fi
done

Run it from the main directory with subdirs containing videos.

I think the problem is the opposite here. The modification time of the directories should be changed, not the modification time of the files inside them.

Diantre 07-29-2011 02:44 PM

Quote:

Originally Posted by colucix (Post 4428681)
I think the problem is the opposite here. The modification time of the directories should be changed, not the modification time of the files inside them.

Oh my! I misread the original post. I suppose my brain is working backwards today. Thank you for your correction, and please disregard my post! :redface:

pjgm 07-29-2011 04:06 PM

wooow Thank you guys !!!

I'm trying but when I run this:

Quote:

#!/bin/bash
cd /home/Public/Concertos
for folder in $(ls -d *)
do touchtm=$(ls -l -time-style +%Y%m%d $folder/* |awk '{print $6}')
touch $touchtm $folder
done
I get

Quote:

ls: invalid option -- e
thanks
pjgm

colucix 07-29-2011 04:48 PM

It should be --time-style (double hyphen). In any case there are valid reasons why using ls in a for loop is not a good idea.

pjgm 07-29-2011 05:25 PM

sorry both doesn't work for me...

just to be more clear...

Giving the same modification date of Movies.mkv to their parent directory

-Movies folder # script should work on every folders on this directory
---- Movie name A folder # This folder should get...
-------- Movie name A.mkv # ...this modification date
-------- movie name A.nfo
---- Movie name B folder # This folder should get...
-------- Movie name B.mkv # ...this modification date
-------- movie name B.nfo
---- Movie name C folder # This folder should get...
-------- Movie name C.mkv # ...this modification date
-------- movie name C.nfo

and just a small note: 'movie A.mkv' can have a different name than the 'Movie A folder'

Diantre 07-29-2011 08:11 PM

pjgm, my apologies for misreading your question and posting the opposite solution. I believe this script does what you require:

Code:

#!/bin/bash

for i in *; do
    if [[ -d $i ]]; then
        # list the first .mkv file in the directory
        movie=$(ls -1 $i/*.mkv | head -1)
        # if a .mkv file was found
        if [[ -f $movie ]]; then
            # get it's modification date
            moddate=$(stat -c %y $movie)
            # and apply it to the folder
            touch -d "$moddate" "$i"
        fi
    fi
done


colucix 07-30-2011 03:50 AM

I've tried my code on your directory structure and it works now, with a minor modification to manage the blank spaces in the directory names:
Code:

while read file
do
  touch -t $(date -r "$file" +%Y%m%d%H%M) "$(dirname "$file")"
done < <(find . \( -iname \*.avi -o -iname \*.mkv \))


pjgm 07-30-2011 03:29 PM

I thank you all

A friend of mine gave me this...

credits to him... Vpeter

Quote:

#!/bin/bash
#
# fix movie folder date
# by vpeter for pjgm
#
# ref
# http://unix.stackexchange.com/questi...ps-recursively
#

# find folders in curent folder
find -mindepth 1 -maxdepth 1 -type d | while read dir ; do
echo -n "Modifying date '$dir' "
# go down
cd "$dir"
# get reference file date
#refFile=$(find -mindepth 1 -maxdepth 1 \( -name "*.avi" -o -name "*.mkv" \) -printf '%T+=%p\n' | sort -n | tail -n 1 | sed 's/[^=]*=//')
# first find .avi file
refFile=$(find -mindepth 1 -maxdepth 1 -name '*.avi' -printf '%T+=%p\n' | sort -n | tail -n 1 | sed 's/[^=]*=//')
if [ ! -n "$refFile" ]; then
# then find .mkv file
refFile=$(find -mindepth 1 -maxdepth 1 -name '*.mkv' -printf '%T+=%p\n' | sort -n | tail -n 1 | sed 's/[^=]*=//')
fi
# file set
if [ ! -n "$refFile" ]; then
echo " - no reference .avi|.mkv file found"
else
echo "using file '$refFile'"
# set date first on folder
touch -r "$refFile" .
# set date on all the other files too
touch -r "$refFile" *
fi
# go up
cd ..
done
thanks again for your time.
Pjgm

Nominal Animal 07-31-2011 09:33 AM

This should do the trick, if you use Bash:
Code:

find ./ -depth -mindepth 1 -type f '(' -name '*.avi' -o -name '*.mkv' ')' -print0 \
| ( IFS=$'\0' ; while read -d "" FILE ; do echo touch -r "$FILE" "$(dirname "$FILE")" ; done )

The first line searches for such files in all subdirectories.
The second line uses touch to set the modification time on the parent directory to match each file found.

If you do not use Bash, or you have a non-GNU find, or old find, use
Code:

/bin/sh -c 'find ./ -type f | while read FILE ; do
    case "$FILE" in
        *.avi|*.mkv)
            ;;
        *) continue
            ;;
    esac
    touch -r "$FILE" "`dirname "$FILE"`"
done'

but note this will b0rk if the file names contain newlines. This latter should work with all POSIX and even some Bourne shells. On SunOS 5.10 (and other old OSes) you may need to replace the touch line with settime -r "$FILE" "`dirname "$FILE"`" to set the directory time.


All times are GMT -5. The time now is 12:03 PM.