4

I want to write a shell program which will go through all folders whose names match a pattern like this:

sudo sh  shell.sh   pub 

When run, the script will look for all folders whose name contains pub and print its modification date. I wish to have code which will print results like in this image: enter image description here I have this code but it is not giving me the result I expect.

echo  'the folder '$1' was modified at ';
 find  -type d -name 'kam*'  -exec stat -c '%y %n' '{}' \;

I must go through every folder and output text echo 'the file '$1' was modified at '; and print the date like in the image.

I would like a result like this:

netcom@hotspot:~$ bash script.sh testRegex Pub
the folder testRegex was modified on may 15 01:19
 the folder Public was modified on may 19 01:19 
  the folder Pubos was modified on may 19 01:19 
Digital Trauma
  • 2,445
  • 15
  • 24
Muh
  • 45

4 Answers4

6

You can use find itself to print the whole thing:

for pattern
do
    find . -type d -name "*$pattern*" -printf 'The folder %P was modified on %t\n'
done

for pattern; do ... done loops over all the arguments, with the pattern variable set to each argument in turn.

With find, %P and %t give the path to the file and modification time in -printf.

muru
  • 197,895
  • 55
  • 485
  • 740
5

You can use bash with the globstar option enabled as in the following script:

#!/bin/bash
shopt -s globstar
for i
  do for k in **/"$i"*/
    do stat -c "the folder %n was modified on %y" "$k"
  done
done

Save it as script, make it executable with chmod +x script and call it as you wanted it:

bash /path/to/script testRegex Pub

Note that this will search for e.g. Pub*, if you actually want to match *Pub*, change **/"$i"*/ to **/*"$i"*/. If you want to shorten the timestamp, try adding | sed 's/:[^:]*$//' to the end of the do stat line. You should also try %N instead of %n, especially when it comes to directory names with spaces this format is preferable.

If you want more fine-grained control over the date format you can use date, substitute the do stat line with the following:

do date -d@$(stat -c%Y "$k") +"the folder $k was modified on %b %d %R"

You can then use the usual date format sequences explained in man date, this one here prints e.g. May 15 01:19 as you requested.

Last but not least, to pretty-print the output of any of the above you can insert a tab after the directory name and use column as follows:

#!/bin/bash
shopt -s globstar
for i
  do for k in **/"$i"*/
    do date -d@$(stat -c%Y "$k") +"the folder $k%twas modified on %b %d %R"
  done
done | column -ts$'\t'

Example run

$ tree
.
├── 1
│   └── 1
│       └── 1
├── 1something
└── 2
    └── 1
$ bash -O globstar -c 'for i; do for k in **/"$i"*/; do stat -c "the folder %n was modified on %y" "$k"; done; done' _ 1
the folder 1/ was modified on 2018-06-07 09:45:28.098693507 +0200
the folder 1/1/ was modified on 2018-06-07 09:45:28.098693507 +0200
the folder 1/1/1/ was modified on 2018-06-07 09:45:28.098693507 +0200
the folder 1something/ was modified on 2018-06-07 09:55:36.066531665 +0200
the folder 2/1/ was modified on 2018-06-07 09:45:28.098693507 +0200
$ bash -O globstar -c 'for i; do for k in **/"$i"*/; do stat -c "the folder %n was modified on %y" "$k" | sed 's/:[^:]*$//'; done; done' _ 1
the folder 1/ was modified on 2018-06-07 09:45
the folder 1/1/ was modified on 2018-06-07 09:45
the folder 1/1/1/ was modified on 2018-06-07 09:45
the folder 1something/ was modified on 2018-06-07 09:55
the folder 2/1/ was modified on 2018-06-07 09:45
$ bash -O globstar -c 'for i; do for k in **/"$i"*/; do date -d@$(stat -c%Y "$k") +"the folder $k was modified on %b %d %R"; done; done' _ 1
the folder 1/ was modified on Jun 07 09:45
the folder 1/1/ was modified on Jun 07 09:45
the folder 1/1/1/ was modified on Jun 07 09:45
the folder 1something/ was modified on Jun 07 09:55
the folder 2/1/ was modified on Jun 07 09:45
$ bash -O globstar -c 'for i; do for k in **/"$i"*/; do date -d@$(stat -c%Y "$k") +"the folder $k%twas modified on %b %d %R"; done; done | column -ts'"$'\t'" _ 1
the folder 1/           was modified on Jun 07 09:45
the folder 1/1/         was modified on Jun 07 09:45
the folder 1/1/1/       was modified on Jun 07 09:45
the folder 1something/  was modified on Jun 07 09:55
the folder 2/1/         was modified on Jun 07 09:45
dessert
  • 39,982
4

The find command can do what you need with one line

You may have a look at the printf action in find
Seeman find for parameters details of printf

Example

find /PATH/TO/SCAN -type d -iname '*pub*' -printf "%p %TY-%Tm-%Td %TH:%TM\n"

-type d        : search for folders
-iname '*pub*' : find the pattern case insensitive
%p             : display path of found folder
%TY            : time Year 
%Tm            : time month
%Td            : time day
%TH            : time hour
%TM            : time minutes
%TS            : time seconds


For more information
Official webpage for GNU find
25 Practical examples of the find command

cmak.fr
  • 8,696
2

Here's a slight variation, which makes use of -regex instead of -names:

find . -type d -regex ".*\($1\).*$" -printf 'The folder %P was modified on %Tb %Td %TH:%TM\n'

This can be either a single-line script or better yet - a function. Call it as so:

./finder.sh 'Vid\|Doc'

This makes for more idiomatic, grep-like approach.

dessert
  • 39,982
Sergiy Kolodyazhnyy
  • 105,154
  • 20
  • 279
  • 497