LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Linux - Newbie (https://www.linuxquestions.org/questions/linux-newbie-8/)
-   -   [shell scripting] Small problem, for each file in directory... (https://www.linuxquestions.org/questions/linux-newbie-8/%5Bshell-scripting%5D-small-problem-for-each-file-in-directory-878460/)

vraptor 05-02-2011 11:44 PM

[shell scripting] Small problem, for each file in directory...
 
Hello, yes i am working on some homework, however i am not here to be spoon fed.
I am trying to get the numerical modification date of each file in a folder.
Ie lets say there is a file called bob and it was modified 2006-11-23
i want to get it into a variable as 20061123

now i currently have this code:
Code:

#!/bin/sh


# Backup Function

        backup()
        {
                echo "Backing up files"
                for filename in *
                do
                # convert file date to compare date
                modifieddate=`ls --full-time $filename |awk '{print $6}'`
                year=`echo $modifieddate | cut -d '-' -f1`
                month=`echo $modifieddate | cut -d '-' -f2`
                day=`echo $modifieddate | cut -d '-' -f3`
                compare="$myear$mmonth$mday"
                echo $mcomparable
                done
                return
        }
backup

however for some reason my output is:

Quote:

20110408
20110401
20110401
20110415
20110401
20110401
20110318
20110318 2011
20110408
20110408
20110408
See how the 2011 has been placed next to it?
i ran it with -x and saw this:
Code:

++ echo 2011-03-18 2011-03-18
++ cut -d - -f3
+ mday='18 2011'
+ mcomparable='20110318 2011'
+ echo 20110318 2011
20110318 2011

however i do not know how to find a way around this?

Thank you for the help.
v

AnanthaP 05-03-2011 01:32 AM

The date format doesn't contain year for files < 6 months old. (Default). Hence the problem. Note that error occurs in March data.

So you have to use a different switch.

I refer you to:
http://www.unix.com/unix-dummies-que...-l-comman.html

This has:
Quote:

ls(C)
*****

ls, l, lc, lf, lr, lx -- list contents of directories

Description
===========
-l
Lists in long format, giving mode, number of links, owner, group,
size in bytes, the time that each file was last modified. The -1
option is assumed. For files less than six months old, minutes and
seconds are included in the modification time and the year is
excluded. For a consistent format, use -T.

-T
Similar to -l, except that the modification time is always displayed
in full, as in this example:

Aug 31 09:37:00 2001

Unless one of the -c or -u options is specified, the modification
time refers only to changes made to the file's data, or the
creation of the file. It does not record the time that changes were
made to the information stored in the inode.
OK.

Kenhelm 05-03-2011 01:54 AM

If $filename contained spaces or file name pattern matching characters such as * ? [ ] it could expand to more than one file name, so two or more lines would be piped to awk.
To stop that happening try putting $filename in double quotes in this line
Code:

modifieddate=`ls --full-time "$filename" |awk '{print $6}'`

vraptor 05-03-2011 03:48 AM

Quote:

Originally Posted by AnanthaP (Post 4344671)
The date format doesn't contain year for files < 6 months old. (Default). Hence the problem. Note that error occurs in March data.

So you have to use a different switch.

I refer you to:
http://www.unix.com/unix-dummies-que...-l-comman.html

This has:

OK.

When i use -T it says i need arguments, also --full-time displays full date, here is an example of my directory:
Quote:

drwxr-xr-x 2 user1 testing 4096 2011-05-03 18:09:35.000000000 +1000 Assignmen t
-rwxr-xr-x 1 user1 testing 201 2011-04-08 13:55:27.000000000 +1000 counter.s h
-rwxr-xr-x 1 user1 testing 60 2011-04-01 14:25:16.000000000 +1100 del.sh
-rwxr-xr-x 1 user1 testing 215 2011-04-01 14:17:05.000000000 +1100 dopt.sh
-rwxr-xr-x 1 user1 testing 507 2011-04-15 13:20:45.000000000 +1000 fit2065te st.sh
-rwxr-xr-x 1 user1 testing 501 2011-04-01 13:38:45.000000000 +1100 guessinga me.sh
-rw-r--r-- 1 user1 testing 253 2011-04-01 14:34:34.000000000 +1100 myvi.sh
-rw-r--r-- 1 user1 testing 105680 2011-03-18 13:22:08.000000000 +1100 test
drwxr-xr-x 4 user1 testing 4096 2011-03-18 13:10:35.000000000 +1100 units
-rwxr-xr-x 1 user1 testing 201 2011-04-08 14:10:57.000000000 +1000 Week6Q3.s h
-rwxr-xr-x 1 user1 testing 82 2011-04-08 14:10:31.000000000 +1000 Week6Q4.s h
-rwxr-xr-x 1 user1 testing 41 2011-04-08 14:21:58.000000000 +1000 Week6Q5.s h
however for some reason one of them, the march ones are displaying as said above.

Also to the person who suggested i put it in quotes, this did not solve the issue either :(

colucix 05-03-2011 04:04 AM

If for some reason the modifieddate variable contains two dates at some point the statements
Code:

$ modifieddate="2011-03-18 2011-04-08"
$ day=`echo $modifieddate | cut -d '-' -f3`
$ echo $day
18 2011

will pick-up the year of the second date. You have to investigate why the $filename variable contains two file names at some point. In any case, you can avoid the cut command and use the substring extraction in bash, example:
Code:

$ modifieddate="2011-03-18 2011-04-08"
$ day=${modifieddate:8:2}
$ echo $day
18

Note that the first character in a string is character number 0 for the shell, so that to extract the 9th and 10th characters the start index is 8.

vraptor 05-03-2011 04:10 AM

Quote:

Originally Posted by colucix (Post 4344766)
If for some reason the modifieddate variable contains two dates at some point the statements
Code:

$ modifieddate="2011-03-18 2011-04-08"
$ day=`echo $modifieddate | cut -d '-' -f3`
$ echo $day
18 2011

will pick-up the year of the second date. You have to investigate why the $filename variable contains two file names at some point. In any case, you can avoid the cut command and use the substring extraction in bash, example:
Code:

$ modifieddate="2011-03-18 2011-04-08"
$ day=${modifieddate:8:2}
$ echo $day
18

Note that the first character in a string is character number 0 for the shell, so that to extract the 9th and 10th characters the start index is 8.

Hmm thank you for the suggestion, i just can't understand why this is happening, i believe using the substring extraction is beyond what we have learnt.
Is it a problem with one of the files themselves, or with my script? I have tried changing around a few things but to no avail :(.

vraptor 05-03-2011 04:13 AM

OH i found the problem, the file it is looking at is a directory! And there are two files inside of it :S how can this be avoided?

colucix 05-03-2011 04:15 AM

The reason is that some of the listed files are directories! If the argument of the ls command is a directory, the output is a list of the content of the directory, not just the directory itself. To avoid this problem use the -d option of ls:
Code:

modifieddate=`ls -d --full-time $filename |awk '{print $6}'`


---------- Post added 03-05-11 at 10:16 ----------

Quote:

Originally Posted by vraptor (Post 4344779)
OH i found the problem, the file it is looking at is a directory! And there are two files inside of it :S how can this be avoided?

You found the solution while I was typing. Well done! Answer to your question in my post above and in man ls! ;)

jschiwal 05-03-2011 04:16 AM

You might want to look at the find command and the date arguments for the -printf command option.
You can control how the date is printed out.

For comparisons, you might want to use the `date' command to express the result in seconds since the reference epic.

vraptor 05-03-2011 04:55 AM

Thank you so much guys, just finished my method to get all the subdirectories too :)
Great community!

David the H. 05-03-2011 05:16 AM

The -d option to gnu date can also be used to convert time strings into the format you want. Just feed the output of stat into it, for example:
Code:


modifieddate=$( date -d "$( stat -c "%y" inputfile )" +%Y%m%d )


MTK358 05-04-2011 09:03 AM

Note that you can also get the modification time of a file using the stat command.

It might be better, since ls's output is mostly meant for human reading, not scripts.


All times are GMT -5. The time now is 06:28 PM.