Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I'm currently learning how to write simple scripts and can't get my head around a very simple problem.

I have the following command in my script...

touch ${DIRECTORY}/${FILE}

This command appears several times in my script and works fine in all instances except for one. For some reason, at one point only, it decides to include the slash in the filename that it's trying to create and I get the error...

cannot touch `/myfile.dat': Permission denied

At first I thought it was just probably down to my inexperience (which it probably is) but after doing a bit of research, I've seen this line used in countless examples working correctly. I can't understand - the same line is working fine in several other locations in my script!

Anybody care to shed some light on this? It's the inconsistency that's really annoying me. Can the commands surrounding this particular command affect its outcome?

share|improve this question

2 Answers 2

up vote 2 down vote accepted

Looks like ${DIRECTORY} is empty. In that case touch ${DIRECTORY}/${FILE} expands to touch /${FILE}

share|improve this answer
    
You mean that ${DIRECTORY} is not getting resolved? –  Rich Dec 6 '12 at 12:04
    
@Rich It's 'resolved' to an empty value apparently. It seems that you or some other script/application you run before that resets/unsets the value of DIRECTORY. Try debug this with some echo $DIRECTORY statements to get some idea where it happens in your script. –  gertvdijk Dec 6 '12 at 12:16
2  
Also possible, it's a mispelling of ${DIRECTORY} the one time it's not working, and the author can't see the wood for the trees. Check very carefully that it's spelled correctly that one time. –  EightBitTony Dec 6 '12 at 12:38
    
..or the simplest answer: since the DIRECTORY is a variable, at some point it is getting set to a place where the user, who is running the script, has no write permission. –  MelBurslan Dec 6 '12 at 23:39

Several things might be happening.

  • Maybe you misspelled DIRECTORY at this point, so the script is running something like touch ${DRIECTORY}/${FILE}. Since DIRECTORY is not set, if $FILE is myfile.dat, this expands to touch /${FILE} (an unset variable is treated as if it was empty).
    You can make the shell stop with an error message if you every try to expand an unset variable. Put set -u at the top of the script (after the #! line). You can switch back and forth between unset-triggers-error and unset-is-empty with set -u and set +u.
  • Maybe the variable DIRECTORY is unset or empty at this point. See previous point.
  • Maybe you accidentally put an extra space: touch ${DIRECTORY} /${FILE}. Then the touch command receives two parameters, it operates on ${DIRECTORY} (which, since this is presumably the name of an existing directory, sets that directory's modification time to the current time), then it chokes on /${FILE}.
  • Maybe there is an extra space at the end of the value of DIRECTORY. For example, if the value of the variable is /some/path with a space at the end, then touch receives two parameters: /some/path and /myfile.dat. See previous point.

Your script won't work if DIRECTORY or FILE contain any whitespace or globbing character \[?*. This is because when you write e.g. $FOO, this doesn't just expand to the value of the variable: that value is then split into words at each whitespace sequence, and each word is interpreted as a wildcard pattern and replaced by matching file names (if no file name matches, the pattern is left alone). Always use double quotes around variable substitutions (and likewise command substitutions). Inside double quotes, "$FOO" expands to just the value of FOO with no further mangling.

touch "$DIRECTORY/$FILE"

(See also $VAR vs ${VAR} and to quote or not to quote)

To get a better idea of what the script is doing, put set -x after the #! line. This enabled a debug mode where the shell prints each command before executing it. You can switch debug traces on and off with set -x and set +x.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.