1

I am trying to write a script-like D program, that would have different behaviour based on availability of certain tools on user's system.

I'd like to test if a given program is available from command line (in this case it is unison-gtk) or if it is installed (I care only about Ubuntu systems, which use apt)

Adam Ryczkowski
  • 7,592
  • 13
  • 42
  • 68

5 Answers5

2

For the record, there is a walk around using e.g. tryRun:

bool checkIfUnisonGTK() 
{
   import scriptlike;
   return = tryRun("unison-gtk -version")==0;
}
Adam Ryczkowski
  • 7,592
  • 13
  • 42
  • 68
  • 1
    I think this is the best way to go. What you want to do is run a program... so just run the program and see what happens. Trying to dig into if the file exists or package is installed and stuff like that is like diving into implementation details when you really should only care about the interface. So I don't think this is a workaround at all, I think it is the correct solution. – Adam D. Ruppe Oct 11 '15 at 17:03
2

Instead of tryRun, I propose you grab the PATH environment variable, parse it (it is trivial to parse it), and look for specific executable inside those directories:

module which1;

import std.process;   // environment
import std.algorithm; // splitter
import std.file;      // exists

import std.stdio;

/**
 * Use this function to find out whether given executable exists or not.
 * It behaves like the `which` command in Linux shell.
 * If executable is found, it will return absolute path to it, or an empty string.
 */
string which(string executableName) {
    string res = "";
    auto path = environment["PATH"];
    auto dirs = splitter(path, ":");
    foreach (dir; dirs) {
        auto tmpPath = dir ~ "/" ~ executableName;
        if (exists(tmpPath)) {
            return tmpPath;
        }
    }

    return res;
} // which() function

int main(string[] args) {
    writeln(which("wget")); // output: /usr/bin/wget
    writeln(which("non-existent")); // output: 

    return 0;
}

A natural improvement to the which() function is to check whether tmpPath is an executable, or not, and return only when it found an executable with given name...

DejanLekic
  • 18,787
  • 4
  • 46
  • 77
  • 2
    This is for sure the better solution. You could even make this work on windows using std.path.pathSeparator variable which is ":" on linux and ";" on windows.. – Colin Grogan Oct 12 '15 at 10:42
1

There can't be any «native D solution» because you are trying to detect something in the system environment, not inside your program itself. So no solution will be «native».

By the way, if you are really concerned about Ubuntu only, you can parse output of command dpkg --status unison-gtk. But for me it prints that package 'unison-gtk' is not installed and no information is available (I suppose that I don't have enabled some repo that you have). So I think that C1sc0's answer is the most universal one: you should try to run which unison-gtk (or whatever the command you want to run is) and check if it prints anything. This way will work even if user has installed unison-gtk from anywhere else than a repository, e.g. has built it from source or copied a binary directly into /usr/bin, etc.

Max Alibaev
  • 681
  • 7
  • 17
  • This approach epically fails when the application is installed by manual compilation, followed by installation (typical `configure --prefix=/usr/ocal; make; sudo make install`)... – DejanLekic Oct 12 '15 at 18:46
  • Why? If a program is within `PATH`, it should be visible to `which` as well. And if not, then we can't run it anyway (if user won't explicitly set path to the binary). – Max Alibaev Oct 13 '15 at 13:19
  • Actually, I was referring to the first half of your comment (dpkg --status) ... I did not notice the part where you mentioned the which tool... – DejanLekic Oct 13 '15 at 14:57
1

Linux command to list all available commands and aliases

In short: run auto r = std.process.executeShell("compgen -c"). Each line in r.output is an available command. Requires bash to be installed.

Community
  • 1
  • 1
weltensturm
  • 2,164
  • 16
  • 17
0
man which
man whereis
man find
man locate
IamK
  • 2,753
  • 5
  • 30
  • 39
  • I know these tools very well. I'm asking if there is a *native* D solution (library) that solves the problem. – Adam Ryczkowski Oct 11 '15 at 11:24
  • Maybe you should simply to check if it's file exists? – Dmitry Bubnenkov Oct 11 '15 at 11:37
  • @user1432751 That's effectively what I did with my answer. The trick is to check if the file exists in the default search path (and perhaps checking the output of `-version`), because one can have the program installed in different locations. – Adam Ryczkowski Oct 11 '15 at 11:42
  • `which` actually *is* somewhat a "native" tool. It basically goes through directories listed in PATH and checks whether executable is there or not. The only difference is that which gives you all alternatives, while when you try to run your program with `program-name` on, say Linux, it executes executable it finds first. – DejanLekic Oct 13 '15 at 15:02