Is Wget or Similar Programs Always Available on Posix Systems

Is wget or similar programs always available on POSIX systems?

Edit in 2019-11-04: I'm rewriting my answer to reflect the importance of ensuring that a transfer isn't tampered with while in flight. I'll leave my original answer below the rule.

I suggest using rsync over ssh to transfer your files. rsync's interface may look overwhelming, but most users may be able to pick rsync -avzP, and if you need more flexibility, rsync can adapt. Using ssh will provide integrity, authenticity, and privacy to your connection.

curl is the de facto standard for http transfers; if plain http or https are preferred, curl or tools based on curl are probably a good choice.


In my experience, tools are available about in this order:

  • wget
  • curl
  • sftp
  • ftp
  • GET (I use HEAD all the time and often forget it is just one tool in the suite)
  • tftp
  • nc (not as common as I wish)
  • socat (even less common)

The bash /dev/tcp tool is available on most systems I've used (some used dash or pdksh instead), but using echo with bash, nc, or socat is going the long-way-around for HTTP access -- you'll have to handle headers somehow, which reduces its elegance.

How to dynamically check for library information in posix compliant systems in C++?

It is library-specific. Each library will have its own method (or might have none) to query what version is loaded.

This is different to querying the system to ask what version of a library is installed--that's the wrong way to go about it because the version loaded in your program might be different to what the system has installed (and the system might have multiple runtime versions installed).

In your specific case, you need to call glfwGetVersion() for GLFW, and use GLEW_VERSION for GLEW.

how to unzip a file using unzip command?

It fails because unzip foo.zip assumes foo.zip is in the current directory, but you just moved it to a subdirectory data. Interactively, you probably cd data first and that's why it works.

To make it work in your script, just have your script cd data as well:

#!/bin/bash
mkdir data
cd data || exit 1
wget http://187.191.75.115/gobmx/salud/datos_abiertos/datos_abiertos_covid19.zip && unzip datos_abiertos_covid19.zip

That way, the file is downloaded directly to the data directory so no mv is necessary, and the unzip command works as expected.

How can I check if a program exists from a Bash script?

Answer

POSIX compatible:

command -v <the_command>

Example use:

if ! command -v <the_command> &> /dev/null
then
echo "<the_command> could not be found"
exit
fi

For Bash specific environments:

hash <the_command> # For regular commands. Or...
type <the_command> # To check built-ins and keywords

Explanation

Avoid which. Not only is it an external process you're launching for doing very little (meaning builtins like hash, type or command are way cheaper), you can also rely on the builtins to actually do what you want, while the effects of external commands can easily vary from system to system.

Why care?

  • Many operating systems have a which that doesn't even set an exit status, meaning the if which foo won't even work there and will always report that foo exists, even if it doesn't (note that some POSIX shells appear to do this for hash too).
  • Many operating systems make which do custom and evil stuff like change the output or even hook into the package manager.

So, don't use which. Instead use one of these:

command -v foo >/dev/null 2>&1 || { echo >&2 "I require foo but it's not installed.  Aborting."; exit 1; }
type foo >/dev/null 2>&1 || { echo >&2 "I require foo but it's not installed.  Aborting."; exit 1; }
hash foo 2>/dev/null || { echo >&2 "I require foo but it's not installed.  Aborting."; exit 1; }

(Minor side-note: some will suggest 2>&- is the same 2>/dev/null but shorter – this is untrue. 2>&- closes FD 2 which causes an error in the program when it tries to write to stderr, which is very different from successfully writing to it and discarding the output (and dangerous!))

If your hash bang is /bin/sh then you should care about what POSIX says. type and hash's exit codes aren't terribly well defined by POSIX, and hash is seen to exit successfully when the command doesn't exist (haven't seen this with type yet). command's exit status is well defined by POSIX, so that one is probably the safest to use.

If your script uses bash though, POSIX rules don't really matter anymore and both type and hash become perfectly safe to use. type now has a -P to search just the PATH and hash has the side-effect that the command's location will be hashed (for faster lookup next time you use it), which is usually a good thing since you probably check for its existence in order to actually use it.

As a simple example, here's a function that runs gdate if it exists, otherwise date:

gnudate() {
if hash gdate 2>/dev/null; then
gdate "$@"
else
date "$@"
fi
}

Alternative with a complete feature set

You can use scripts-common to reach your need.

To check if something is installed, you can do:

checkBin <the_command> || errorMessage "This tool requires <the_command>. Install it please, and then run this tool again."

unix & gnu/linux distributions: possible locations for 'which' command?

which is not a standard part of linux systems. It's not present in Linux Standard Base 4.1, and not present in Single Unix Specification Version 4/POSIX 2008:

  • http://refspecs.linuxfoundation.org/LSB_4.1.0/LSB-Core-generic/LSB-Core-generic/toccommand.html
  • http://pubs.opengroup.org/onlinepubs/9699919799/idx/utilities.html

So the only formal answer for the question is that which has no reliable location in the file system.

For the practical solution: which should always be available in the default search path directories. So the best practical answer: run which from your script without a hard coded path. [Edit: any solution with a set of hard coded paths is worse than using the default search paths].

Is there an equivalent to COM on *nix systems ? If not, what was the *nix approach to re-usability?

The Unix model is built around the idea of lightweight processes that communicate with each other, through sockets, pipes, signals, and command lines. Historically, Unix didn't have threads (the POSIX thread model is only about 10 years old IIRC), but processes on Unix have always been much cheaper than on Windows, so it was more performant to factor functionality into separate executables than to allow a single program to grow large and monolithic.

In COM, you define binary interfaces that allow shared-memory communication. COM is tied to an object-oriented paradigm. In the classic Unix model, you define stream-oriented interfaces that allow communication over pipes, without shared memory. Conceptually, this is much closer to a functional programming paradigm.

The Unix model encourages making small programs that can be easily coupled together by a lightweight "shell", while the COM model encourages making large programs that expose "components" that can be reused by other large programs. It's really an apples-and-oranges comparison, since both models provide benefits and drawbacks for different scenarios.

Of course, modern Unix systems can have COM-like facilities. Mozilla has XPCOM, a cross-platform framework built on the same principles as COM. GNOME for a long time used Bonobo, which is conceptually very similar to Microsoft OLE, which was the forerunner to COM. But recent versions of GNOME have been shifting away from Bonobo in favor of D-Bus, which is more of an event/messaging pattern.

Give a wget downloaded file executable rights without chmod?

You can't. It's as simple as that. Unix permissions are not transferred by HTTP. To do this, you would need to use other tools, e.g. rsync or scp.



Related Topics



Leave a reply



Submit