0

I have a problem with the use of the date command in a shell script; this is my script:

#!/bin/bash

for i in $(find . -type f -mtime +10 ); 
do
    echo "$i"
    echo "ligne dans la boucle";
    #il faut verifier si il a ete créer un samedi ou pas;
    jour=`ls -lrt $i| awk '{print $7}'`;
    mois=`ls -lrt $i| awk '{print $6}'`;
    annee=`ls -lrt $i| awk '{print $8}'`;
    requette="date -d '$mois $jour $annee' +'%a %u %A'";
    echo $requette;
    test=$($requette);
    echo $test;
    echo " ";
done

So the output is like this:

date: extra operand ‘2015'’

but when I use the command directly on the shell it works :/

requette="date -d 'Feb 28 2015' +'%a %u %A'"

If anyone can help me that would be great!

wogsland
  • 401
  • 2
  • 8
  • 19
Kingofkech
  • 1,028

2 Answers2

3

You can considerably simplify matters by using the stat command in place of ls.

#!/bin/bash
for i in $(find . -type f -mtime +10 ); 
do
   echo "$i"
   echo "ligne dans la boucle";
   #il faut verifier si il a ete créer un samedi ou pas;

   #///////////////////////
   #jour=`ls -lrt $i| awk '{print $7}'`;
   #mois=`ls -lrt $i| awk '{print $6}'`;
   #annee=`ls -lrt $i| awk '{print $8}'`;
   #requette="date -d '$mois $jour $annee' +'%a %u %A'";
   #//////////////////////////////

   # get the month, year, and day from stat-ing the file
   mois_jour_annee=`stat -c '%y' "$i" | cut -d' ' -f1`

   # and then...
   requette="date -d '${mois_jour_annee}' +'%a %u %A'";

   echo "$requette";
   test=$(eval "$requette");
   echo "$test";
   echo " ";
done
  • See my comment on the question. Since this is a copy-paste of OPs code (except for the ls part which was replaced by stat) it has the same pitfalls and problems as the OP's code. – don_crissti Mar 01 '17 at 12:36
3

If you want to find regular files that are more than 10 days old and that have been last modified on a Saturday (in the timezone of the user running the script), with GNU tools (and you seem to be on a GNU system as you're using a GNU-specific option to date and the GNU shell), you can do:

find . -type f -mtime +10 -printf '%Tu%p\0' |
  sed -zn 's/^6//p' |
  tr '\0' '\n'

While GNU eventually added (yet a different) stat command in the early 2000s to query file metadata in a more scriptable fashion that with ls, most of its functionality was already in GNU find long before that and with a much better interface than GNU stat's.

Most other stat implementations can give you the modification time in any format, GNU stat can't (the reason why you end up resorting to a combination of ls and GNU date in your question I suppose) but GNU find can (with GNU date, you could also use date -r "$file" +%u).

Above %T<format-letter> is the modification time using the specified strftime format. %Tu is the day of the week as a number from 1 (Monday) to 7. That's better in scripts than using %a/%A that are locale dependant.

We're printing that number followed by the file path, NUL delimited to be able to handle file names with newline characters, and piping to sed to select the records that start with 6 (and remove that 6 for them). The NULs are then translated to newline on output.

-z was added to GNU sed in 2012. If your sed is older, you can change the above to:

find . -type f -mtime +10 -printf '%Tu%p\0' |
  tr '\0\n' '\n\0'
  sed -n 's/^6//p' |
  tr '\0' '\n'

Generally, you don't want to loop over the output of find like you do in your question. If you wanted to loop over the files found by find in bash, you'd rather do:

 while IFS=/ read -d '' -ru3 day file; do
   case $day in
     (6) printf '"%s" was last modified on a Saturday\n' "$file";;
   esac
 done 3< <(find . -type f -mtime +10 -printf '%Tu/%p\0')

In zsh, you could also do:

zmodload zsh/stat # for zsh's stat builtin
last_modified_on_a_saturday() {
  local -A stat
  stat -LF %u -H stat -- ${1-$REPLY} &&
    ((stat[mtime] == 6))
}
for file in **/*(ND.m+10+last_modified_on_a_saturday); do
   do-something with $file
done