Automate "touch" bash script not working.

#!/bin/bash -i
SAVEIFS=$IFS
IFS=$"\n\b"

picc=$*
if [ -f "$picc" ]; then
echo $TDATE
if [ ! -z "$TDATE" ]; then
 touch dummy
 touch -t "tdate" dummy
 touch -r "dummy" "$picc"
else
    echo -e "No mod date value to apply. If there is one in your shell,\ninvoke \e[7msuperdate\e[0m and try again."
    exit 1
fi
fi
IFS=$SAVEIFS

Started asking advice on this (on Linuxquestions.org). The last time I ran the script, this happened.
the script, when I run it, is neither changing the date of the file pointed to nor creating the file "dummy." And the command in line 15 the script, when I run it, is neither changing the date of the file pointed to nor creating the file "dummy." And the command in line 15 isn't even returning an "empty variable" kind of error. In short, the script does nothing I can discern between running it and not running it.

Anyone care to advise me?

Carver
Go here: Automate "touch" bash script not working. for the original discussion

Start with the standard explanations:

  • what OS are you using?

  • what shell are you using?

  • please describe (in plain text) what you are about to achieve.

From the quoted and linked discussion i take it you don't understand what export variable does and you don't understand how to create and use variables and what their scope is (that is: where they keep their values and where not). From your script i take it you don't know how to handle command line options either.

I will be glad to explain all that (and maybe more) to you once you have told us what the (real!) underlying motivation for your script is because chances are you need some other explanation(s) either in addition or instead of knowing how to handle variables, command line arguments, etc..

I hope this helps.

bakunin

GNU bash, version 4.3.48(1)-release (i686-pc-linux-gnu)
LinuxMint 18.3 KDE 5.5.x

I wish to export the value of a variable (a date in MMDDYYHHMM.SS format; in the script: tdate or TDATE) set in a terminal shell to a script that will change the modification date of a file (referred to by the value of another variable, here picc) without my having to type in the relevant command. I have my laptop on an ordinary desk (in fact it has an Ethan Allen stamp on the inside of the drawer). My laptop has a 17" screen, and on the only chair I have for the desk, the armrests are too high for me to slide them under it. This makes it difficult for me to reach the laptop's keyboard, so I am using an ordinary desktop keyboard, set at an angle with the bottom resting on a ridge inside the front of the drawer. Therefore, I have to type "uphill," as I call it, an unconventional ngle in my experience, for typing. And since my typing is not the sort as taught in high school or business schools, I try to get away with doing as little of it as possible.

But enough of all that. I went about that explanation so you would know that, besides a script that isn't doing what I'd like, I have other challenges to contend with. No one on linuxquestions knows about them

It was indeed unfair of me not to put my OS, shell version and hardware in my signature on this forum. I will do so as soon as I finish this post.

wrong

1 Like

You are first using variable TDATE without setting it then trying to use tdate (without a $ either) to set the timestamp of your file so could these be issues?

What are you trying to actually achieve?

If you stick to one variable name, perhaps this will help:-

TDATE=201612311234
touch -t $TDATE /tmp/dummy

This should set the file /tmp/dummy to have timestamp of 12:34 on the last day of 2016.

Does that help?

Robin

That you are typing at an angle isn't relevant. The computer doesn't know or care.

TDATE is not set. That is why it is not working. You have to set it or inherit it from somewhere. It won't just appear because you want it to.

I must assume you are setting it somewhere else, or attempting to set it from somewhere else. This is the bit you haven't explained. You also haven't explained how you are running this program - manually, from cron, whatever.

First,

#!/bin/bash -i

tells the interpreter that this is an interactive shell and it reads your .bashrc file before executing the rest of your script. Is this what you want?
Secondly consider this:

#!/bin/bash 
IFS=$"\n\b"

picc=$*

printf "%s\n" $picc

Let's call it picc:

$ ./picc

$ ./picc eeny
ee
y
$ ./picc eeny meeny
ee
y
mee
y

You have changed $IFS to be "nb" not "\n\b" .
Change the line

IFS=$"\n\b"

to

IFS=$'\n\b'

and try again:

$ ./picc

$ ./picc eeny
eeny
$ ./picc eeny meeny
eeny
meeny

Somehow I don't think you are expecting either of those behaviours for $picc . It looks to me as though you are expecting one word. Do your filenames have spaces in them?

When you get that right maybe the rest will slot into place. Until you do what happens with $tdate won't matter.

Andrew

2 Likes

Dear iamwrong,
I hope we haven't driven you to another forum already. After considering you script I've come up with this albeit over-engineered script which may have the behaviour I think you wanted. I have included comments to explain why I ave done the things I have.

#!/bin/bash         
                    # no need for the -i option
                    # IFS statements removed as you don't actually need them

usage() {           # Few do it but you really should have a usage
                    # function even on a script this short
   printf "Usage: %s file\n" ${0##*/}
   printf "Where file is the file to be timestamped.\n"
   printf "Remember to quote the filename if there are spaces in it.\n"
   printf "Example: %s %s\n" ${0##*/} $'"my holiday snap.jpg"'
   printf "Required environment variable: TDATE\n"
   printf "Please ensure it is exported with %s\n" $'\e[7msuperdate\e[0m'
}

if [ -z "${TDATE}" ]    # Do this test first
then                    # exit if it fails
   printf "\nTDATE not set\n\n"
   usage
   exit 1
fi

ref_file=/tmp/${0##*/}$$        # set up your reference file
trap 'rm -f "${ref_file}"' 0    # remove the reference file on exit
                                # The -f silences rm if file hasn't been created
                                # when we exit
trap 'exit' HUP INT QUIT ABRT TERM  # clean exit on any of these interrupts
                                    # Probably not useful in this short script

touch -t "${TDATE}" "${ref_file}"

picc="${1}"
if [ -z "${picc}" ] || [ ! -f "${picc}" ]
then    # can't find $picc
   printf "\nCannot find file to update!\n\n"
   usage
   exit 1
fi

touch -r "${ref_file}" "${picc}"       # business of this script 

# exit trap clears the reference file

I am guessing that the reason you used

picc=$*

in your original code was to allow for spaces in your file names. If so this script is more likely to work the way you wanted it to.

I hope you find this useful. As I said it is somewhat over-engineered, what with using a reference file for the touch command and the resultant interrupt handling, as well as the usage function.

Andrew

All of you are going to hate this. (I'd tell the folks on linuxquestions.org too but the site seems to be down at the moment.)

It turns out "autotouch," along with existing as a script, was a function in my .bash_aliases file. It was the function being invoked instead of the script. The function reads as follows

function autotouch () {
if [ ! -z "$tdate" ]; then
touch dummy
 touch -t "$tdate" dummy
 echo "The empty file, dummy, is now dated as follows"
 stat -c %y dummy
 touch -r "dummy" "$picc"
 rm dummy
fi
}

And when invoked, the function does not remove 'dummy.' At this point, I'd just like to know why it doesn't.

iaw

I have just tested your function and it works for me.

Double check the following:

  • Does "dummy" already exist as a file?
  • Is "$tdate" set prior to invoking the function?

Also just check that there isn't another autotouch being invoked by typing

type autotouch

and comparing the output with what you expect.

Andrew

apmcd47: Thank you very much. I saved your sample script as autotouch-b and it works great. I think what I was forgetting to do was use the 'superdate' in my .bash_aliases file, so I wrote a separate script that has that function, then calls the original autotouch script (which passes TDATE to dummy, copies it back to the target file, then deletes it with my nodummy script).

Thanks again, a thousand thanks again.

wrong