3

I'm trying to write my first ever shell script. The code I have written must be executed whenever a certain database has been modified. The database resides on a Windows server to which I have a mount point. Here is the script I have written to date:

#!/bin/sh

DB1=/mnt/reckon/"Point of Sale Lite 2013 Administrator"/QBPOS.PDB

ls -la "$DB1"

if [ "$DB1" -nt "~/scripts/file1" ]; then
  echo "Database has updated since last run"
  echo "Do some stuff here"
  touch file1
else
  echo "Database has not been updated"
fi

Unfortunately, no matter what, the script ALWAYS equates to false. This is an ls of DB1 at the beginning of the script just for debugging so I can see if the DB1 declaration is successful.

This is an ls for my file1:

pi@mckinnonPi ~/scripts $ ls -l file1
-rw-r--r-- 1 pi pi 0 Jun 20 10:27 file1

This is an ls for the database:

pi@mckinnonPi ~/scripts $ ls -l /mnt/reckon/"Point of Sale Lite 2013     Administrator"/QBPOS.PDB
-rwxr-xr-x 1 root root 2048000 Jun 22 14:30 /mnt/reckon/Point of Sale Lite 2013     Administrator/QBPOS.PDB

As you can see the database file is certainly newer than file1, however if I now run the script this is what I get:

pi@mckinnonPi ~/scripts $ ./fileage 
-rwxr-xr-x 1 root root 2048000 Jun 22 14:36 /mnt/reckon/Point of Sale Lite 2013 Administrator/QBPOS.PDB
Database has not been updated
pi@mckinnonPi ~/scripts $ 

So clearly the declaration for DB1 is working, as the ls command in the script succeeds, but for some reason the file age test fails. I've been working on this for a few days now, and I've researched as much as I can but have hit a brick wall. Any help would be very much appreciated.

Thank you!

  • Update

I've re-written the script in order to simplify as much as possible. When using paths that do NOT contain a space everything works exactly as expected so when I run this script:

#!/bin/sh

# DB1=/mnt/qnap/Amarillo/Reckon/"Point of Sale Lite 2013 Administrator"/QBPOS.TXT
DB1=/tmp/test/file2
TF1=/home/pi/scripts/file1

ls -la "$DB1"
ls -la "$TF1"

if [ "$DB1" -nt "$TF1" ]; then
    echo "Database has been updated since last run"
    echo "Do some stuff here"
    touch /home/pi/scripts/file1
else
    echo "Database has NOT been updated"
fi

The conditional statement works exactly as I would expect. Unfortunately, when I change the test to use the path including spaces it fails again. This is so frustrating! I've also tried using a symbolic link but the same problem occurs.

OK, so I'm new to stack overflow, so I don't understand how this has been marked as duplicate and answered? As I have explained in my update above, removing all reference to the tilde makes NO DIFFERENCE, this problem has nothing to do with the tilde expansion, as you can see in the updated code above.

Please don't mark something as answered if you have not read and understood the question fully .

8
  • Are you running Ubuntu (or an Ubuntu derivative)? Commented Jun 22, 2014 at 4:51
  • 3
    You are quoting the tilde. Don't. Commented Jun 22, 2014 at 4:52
  • Thanks for the response. I am running Raspbian on a Raspberry Pi. Commented Jun 22, 2014 at 6:57
  • Removed any reference to tilde just to be sure. Still get the same result. Commented Jun 22, 2014 at 10:15
  • I cannot reproduce your results. Can you rewrite the script such that it is self-contained (i.e creates all files it uses and places everything under /tmp)? Commented Jun 22, 2014 at 17:26

3 Answers 3

2

While others have correctly noted that placing a ~ within quotes will prevent shell expansion, you are free to move it outside the quotes and expansion will then work fine. For example the following works fine:

#!/bin/sh

if [ -f ~/"fname w spaces.txt" ]; then
    printf "fname w spaces -- Found\n"
else
    printf "fname w spaces -- NOT Found\n"
fi

exit 0

In your case, changing the if conditional to the following and moving the ~ outside the quotes will allow expansion:

if [ "$DB1" -nt ~/"scripts/file1" ]; then
Sign up to request clarification or add additional context in comments.

7 Comments

Thanks for your reply. I've tried re-writing the entire script, this time removing quotes around the tilde entirely to simplify things as much as possible. Unfortunately the if statement still fails :(
@user3746802 show me the if statement your are using (and the updated code containing all relevant variable assignments), and show me a readlink -f to the fname\ w\ spaces.txt you are trying to test. For example readlink -f fname\ w\ spaces.txt. That will provide the complete path for the file so we can verify your setup.
Moving the tilde outside the quotes will allow it to expand, but it will also allow it to wordsplit, defeating the point of having the quotes around the rest of the string. At that point, it's probably better to use "$HOME/file with spaces.txt".
Hi David. Here is the output requested: pi@mckinnonPi ~/scripts $ readlink -f /mnt/qnap/Amarillo/Reckon/Point\ of\ Sale\ Lite\ 2013\ Administrator/QBPOS.TXT /mnt/qnap/Amarillo/Reckon/Point of Sale Lite 2013 Administrator/QBPOS.TXT pi@mckinnonPi ~/scripts $
And I have added the updated code to the bottom of the original post so it looks neat, pasting it in these comment field is very ugly :)
|
0

Judging from the listing you provided, I think that the problem is that you either have multiple spaces or a TAB after "2013". If you use whitespace in a pathname, Linux is not going to use clever fuzzy matching to try and figure out what you / the user means. As far as Linux pathnames are concerned, one space is different to two ... etc.

A second problem (spotted by @n.m !) is that you are quoting the pathname starting with ~. That will suppress the expansion of the ~ to the user's home directory.


In addition, I would have written the first line as:

    DB1="/mnt/reckon/Point of Sale Lite 2013 Administrator/QBPOS.PDB"

It doesn't make any material difference, but it is (IMO) neater.

Also, I would try to avoid using or allowing pathnames with whitespace in Linux applications them because they tend to be troublesome. It is not uncommon for scripts to be written on the assumption that there are no whitespaces. It is easiest to "play it safe".

4 Comments

I've just tried re-typing the entire script from scratch, avoiding any form of copy and paste. I still get the same error so I don't believe there are any erroneous spaces, tabs etc. I also agree on the second point making reading the code easier. I had tried every permutation available but no difference in outcome I'm afraid.
In that case, you must have made a mistake in copy-pasting the directory listing into the Question, because it has TWO spaces there.
Could you please show me exactly where there are 2 spaces? I have looked again and can not see any double spacing. If you are referring to the 'ls' output then perhaps it was a pasting mistake, but I can;t find any double spacing in the actual shell script that may be causing the issue Thank you.
Look for this line: ls -l /mnt/reckon/"Point of Sale Lite 2013 Administrator"/QBPOS.PDB. Open the Question in edit mode and count the characters.
0

Instead of #!/bin/sh I changed it to #!/bin/bash and it is now working perfectly. For some reason dash does not support the -nt test flag under certain conditions. It works just fine when all files are stored on the local filesystem, but refuses to work correctly accessing network shares.

Changing the shell to bash "#!/bin/bash" solved the problem and now the script works perfectly. Thank you to everyone that helped, I have learned a lot from this little exercise!

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.