Why is ./ sometimes needed?

Hi bakunin...

Ha ha, yes i know about > filename but ':' is something else that the OP has learnt and is much more pleasing to the eye. <wink>

':' is a NOP or true, (or NULL), and can even be used as a command that does nothing at all but is a place-marker for code under development.

1 Like

If you want an exit code that clearly shows whether or not the script successfully created the two files it is trying to create, a simpler solution would be:

#!/bin/sh
# Usage: cleanup2 [Directory_Full_Path]
# POSIX compliant (sort of... POSIX does not require that /bin/sh be the
#                             pathname of a conforming shell).
# When using the default '/var/log/' this HAS to be run as root.
# No need to detect root as the error generated by redirection is enough
# and this script can be used by other users when a different directory is
# given as an operand.

# Use given directory path if present, otherwise default to /var/log.
LOG_DIR=${1:-/var/log}

# Clear the required files.
# The exit code will be zero if and only if both files are successfully cleared.
> "${LOG_DIR}/message" > "${LOG_DIR}/wtmp"

Note that the last line could be replaced by:

> "${LOG_DIR}/message" && > "${LOG_DIR}/wtmp"

or:

: > "${LOG_DIR}/message" > "${LOG_DIR}/wtmp"

or:

: > "${LOG_DIR}/message"
: > "${LOG_DIR}/wtmp"

and get exactly the same results. You don't need a null command or a placeholder for a command when the command(s) that is(are) being executed is a(are) redirection(s). Why give the shell extra work to do parsing an extra command that isn't needed to get the job done?

Note also, however, that the two commands:

: > "${LOG_DIR}/message"
: > "${LOG_DIR}/wtmp"

(and any of the other suggestions above) do not necessarily produce the same results as:

> "${LOG_DIR}/message"
> "${LOG_DIR}/wtmp"

Since : is a shell special built-in utility, the shell will exit with a non-zero exit code if the first : command fails due to a redirection failure, but the last form will not. So, if the script fails to clear message but successfully clears wtmp the last form above will produce a zero exit status while all of the other suggestions in this post will correctly produce a non-zero exit status indicating that at least one of the files was not cleared.

2 Likes

Hi Don...

Check your double quotes, some have one too many.
And just as an addendum, from 'shellcheck', see attached image...

2 Likes

Hi wisecracker,
Thank you for catching the mismatched double-quotes. I was trying to change "$var"/string to "$var/string" and didn't complete the job in a couple of lines.

I'm sorry that shellcheck doesn't like stand-alone redirections. They are part of the shell command language and there is no need to combine them with another command when used as they are used in the script being discussed in this thread.

Note also that the commands:

true > "${LOG_DIR}/message"
true > "${LOG_DIR}/wtmp"

produces the same results in the script being discussed in this thread but runs slower and just like:

> "${LOG_DIR}/message"
> "${LOG_DIR}/wtmp"

will give a zero exit status even when > "${LOG_DIR}/message" failed if > "${LOG_DIR}/wtmp" succeeded.

Of course, the discussion would be different if other pipelines that send output to standard output without redirecting that output were to be included in the script after these redirections; but that isn't the case here in cleanup2 . Nonetheless, I should have stated this assumption in the example I provided.

2 Likes

Wow! My question grew some legs!
I aspire to reach the level of understanding evident in this thread.
Is there a way I can make a humble donation to support this great site?

Thanks Don...

There is this however, reference to OSX 10.14.1, default bash terminal:

Last login: Thu Jan 31 12:05:01 on ttys000
AMIGA:amiga~> man true
AMIGA:amiga~> help true
true: true
    Return a successful result.
AMIGA:amiga~> man false
AMIGA:amiga~> help false
false: false
    Return an unsuccessful result.
AMIGA:amiga~> man :
No manual entry for :
AMIGA:amiga~> help :
:: :
    No effect; the command does nothing.  A zero exit code is returned.
AMIGA:amiga~> 
AMIGA:amiga~> which true
/usr/bin/true
AMIGA:amiga~> which false
/usr/bin/false
AMIGA:amiga~> which :
AMIGA:amiga~> _

Both XUbuntu56 and I can learn from your expertise on this.
I have not copied and pasted the man pages but they do exist.

As you can see there is a manual AND a help entry for "true" and "false", do I take it the some shells, perhaps dash or ash, do not have these as builtins as it looks like I have both builtin and transient versions.
":" is builtin only so I assume that in POSIX this IS a requirement but the others are optional?

TIA.

Bazza...

Well, the best donation would be to continue visiting, raising meaningful, interesting, and challenging questions, LEARNING and APPLYING what you've learned, and finally contributing wise and witty answers.

On top of this, you may become a VIP member with additional benefits.

(Apologies for any typos.)

You will soon become proficient at writing basic shell scripts and the fact that you are willing to learn means you will be able to help others in the not too distant future; not with the subtleties that these professionals know but like myself certainly good enough, but perhaps in your case on [?]Ubuntu and derivatives and closely related OSes.

Try thinking of a simple app' for yourself and writing it in a shell, bash and ksh are probably the way to go, usually bash.

I started learning on this site doing a text mode Audio Oscilloscope and what started as simple idea is now a highly sophisticated FUN application. (I have left some of my original coding in the project still just to see how i have advanced over the years.)

AND our motto:
Those prepared to help themselves and try to solve their own coding problems will certainly get our help if they are stuck with solving them.

Have fun developing your own ideas as this will steer you towards other languages to learn.

Bazza...

The : utility is required by the standard to be a special shell built-in utility.

If you have initialized PATH to the set of directories defined by your operating system to contain all of the standard utilities, the standard requires that the false and true utilities be available either as regular shell built-ins or as stand-alone utilities in one of the directories in PATH . Furthermore, if you are using things like:

find -exec command_name "{}"

where command_name is the name of a standard utility (including both false and true , but not : ) with PATH set as described above), it is required to be found even if it is supplied by your shell as a regular built-in. If, however, command_name is the name a special built-in utility (including : ), the results are undefined.

And, despite what the macOS true and : man pages say the following sequence of commands (attempting to run the : and true commands) with redirections that fail:

bash
bash-3.2$ : >/unknown/unknown
bash: /unknown/unknown: No such file or directory
bash-3.2$ true >/unknown/unknown
bash: /unknown/unknown: No such file or directory
bash-3.2$ echo $?
1
bash-3.2$ : >/unknown/unknown
bash: /unknown/unknown: No such file or directory
bash-3.2$ echo $?
1
bash-3.2$ 

both produce non-zero exit codes and diagnostic messages written to the standard error output. This was run on macOS Mojave version 10.14.2. Before you say that the man pages are wrong, look more closely at the diagnostics. The diagnostics are coming from bash ; not from the : or true utilities. The shell is performing the redirections before invoking the utilities and since the redirections are failing, the utilities are not invoked. You have to be able to run : and true before they can return a zero exit code.

Are we having fun yet? :smiley:

1 Like

Hi Don...

I was aware that bash created the error report but didn't know that part of the standard included certain transient commands.
I appreciate the '/bin/echo' and '/usr/bin/printf' have to be around so that if 'bash' is used as 'sh' as in OSX then these have to override the builtins.
I had great fun getting '/bin/echo' to work with escape codes but it is easily possible in 'dash'.

Anyhow we have command[]eered this thread and I am now clear. Thanks to all including the OP for putting up with me.

See attachment, I have left the error in, my typo fault: