Linux - SoftwareThis forum is for Software issues.
Having a problem installing a new program? Want to know which application is best for the job? Post your question in this forum.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
Distribution: Ubuntu & Mint LTS, Manjaro Rolling; Android
Posts: 242
Rep:
Any replacement for 'which' command?
To see if some application (e.g. meld) is installed on a given system, the traditional method was to use
Code:
which meld
and this would either return nothing or something akin to "/usr/bin/meld" and a shell script could continue doing its job based on the return.
While recently writing such a script, it became apparent that the "which" command returns nothing for a growing percentage of the software on many systems. So far as I can tell, it doesn't recognize (or even know about) things like AppImages, FlatPaks, Snaps and such.
A slightly more difficult approach would be
Code:
dpkg -l meld
or even
Code:
apt-cache policy meld
but those have the same failing.
The output of the command
Code:
sudo apt-cache search gimp
for instance, like that of any app included in a distro, is probably useless, since this is not the same as "GIMP_AppImage-release-2.10.22-withplugins-x86_64.AppImage"
One could, I suppose, parse the various menu layout files, but there is no need or requirement for apps such as those mentioned to include themselves in the menus. Searching for a matching file with any "x" permission seemed as if it wouldn't be very efficient, and much care would need to be taken to determine that case-specific "GIMP_AppImage-release-2.10.22-withplugins-x86_64.AppImage" with an executable bit set is actually a match for the lower case "gimp" - not to mention that this file could be located pretty much anywhere - so before pursuing some ugly hack, I thought I would ask:
Given the growing prevalence of such all-in-one application packages, is there some newer utility around that addresses this?
The "which" command has been part of a standard Unix and Linux for at least 35 years (I even used it on Microsoft Xenix before Windows existed) so its usefulness is certainly not in question, but it seems as if it's no longer able to fulfil its purpose. Any thoughts?
I use locate. It's not perfect, but it's available. It's not available by default in many distros, but it's in most repositories. It's one of the first additions I make to my installations. But I don't use flatpacks, snaps, appimages, or any of the other stuff, so I have no idea if it finds those. For applications, I generally use apt-cache policy with wildcards or search without wildcards. That usually gives a long list, but piping it through grep helps. I don't think there is any better way for what you want. I wouldn't bother to learn or to type in long complicated package names. That's rather useless, but using wildcards makes it somewhat easier.
which shows the full path to the program by searching the users path that runs the which command. That does not necessarily mean the program is not installed just not in that users path environment.
On the other hand the find command will search the entire directory tree for files.
locate is based on a database and not necessarily installed by default. updates only run once a day so recently installed or deleted programs may or may not be displayed.
Distribution: Ubuntu & Mint LTS, Manjaro Rolling; Android
Posts: 242
Original Poster
Rep:
Thanks for the unusually quick responses ...
I should have mentioned find and locate (which I did indeed play with), but each presupposes some specific knowledge, and/or some pretty elaborate regular expressions, since there seems to be no naming conventions in use.
Consider the following situation: you have a general script that is intended to do "something" (add, update, whatever) based on whether the machine/user in question is using gimp (or LibreOffice or whatever). The user may have either "normal" gimp, an AppImage, FlatPak, Snap or - shudder! - more than one of those formats installed, and - extra shudder! - possibly more than one version of one or more of them. (and, remember, the naming might not be the same across these formats, even for the same app).
Without getting into the merits or dangers of having multiple versions of an app installed (depends on the app of course), this seems to occur reasonably often enough that I thought I may just have missed some easy yet reliable solution.
If my impression of the way separate packaging systems (flatpack, snap, appimage, et alia) work is correct, and it certainly may not be correct, there is no reliable way to find them that I know of. An appimage isn't installed AFAIK, it just sits anywhere in the filesystem and the OS doesn't know about it until it's run. I suspect that find, cumbersome as it is, may be the only way to detect these types of files. They aren't in any database that I know of, they're just files which can be anywhere - /home, an external drive, or anywhere at all. It would be necessary to search the entire filesystem every time, and find can do that.
which returns the pathnames of the files (or links) which would be executed in the current environment.
And it works exactly as it was described.
What you need is a different functionality and most probably you need to implement it yourself (to do exactly what you need).
which is a C-shell builtin. A /usr/bin/which exists to emulate it for other shells.
The standard shell has the type builtin.
Unfortunately each shell has a slightly different output format and different options.
In bash
Distribution: openSUSE, Raspbian, Slackware. Previous: MacOS, Red Hat, Coherent, Consensys SVR4.2, Tru64, Solaris
Posts: 2,803
Rep:
Quote:
Originally Posted by CVAlkan
...
While recently writing such a script, it became apparent that the "which" command returns nothing for a growing percentage of the software on many systems. So far as I can tell, it doesn't recognize (or even know about) things like AppImages, FlatPaks, Snaps and such.
...
I always thought (no, I haven't studied its source code) that 'which' simply searched one's PATH for an executable of the specified name. If I'm logged in as a non-root user and issue 'which' for some commands, I'm going to get a message that that application couldn't be found:
Code:
$ which fdisk
which: no fdisk in (/home/rnturn/bin:/usr/local/bin:/usr/bin:/bin:/usr/bin/X11:blah-blah-blah
$
If I'm logged in as root, it's, obviously, a different story.
If a Snap, etc., isn't making an application visible to the PATH that most people use, that just seems like a huge oversight. If a Snap installer (or any other) can't be bothered to at least create a symbolic link in /usr/bin pointing to a snap-installed application's binary, I can't see how that's 'which's fault for not anticipating that Snap and other application packagers would drop the ball.
I have only installed a single application via Snap (the LetsEncrypt utility) and had no issues when running it. I would not be surprised to find a certain degree of undisciplined coding by some of these application packagers. Perhaps the tools for Snap (and others) package creation aren't as mature as those for, say, RPMs and the other package formats that have been around forever.
You may have to write a wrapper around 'which' that fills in the gaps. [Ugh!] Then some Einstein will decide that Homebrew needs a bigger presence on Linux.
Distribution: Ubuntu & Mint LTS, Manjaro Rolling; Android
Posts: 242
Original Poster
Rep:
Once again, thanks for the responses.
To be clear, I was not at all "dissing" any existing functions - merely pointing out that (as pan64 suggests) some new functionality is or may be required to augment them in light of the growing prevalence of all-in-one app formats.
I agree with rnturn that some coding is "undisciplined" though in the case of these sorts of app I'd be more tempted to say it was the design or architecture that was lacking.
I hadn't thought of adding symbolic links when dropping one of these apps on a system; that might help in cases where only one version was present in the path (one could, for example, create a link named "gimp" to "/whatever/GIMP_AppImage-release-2.10.22-withplugins-x86_64.AppImage"), which would work with "which" and certainly save some typing when executing gimp from the command line. But that wouldn't easily support the presence of multiple flavors/versions of gimp.
Now - off to begin working on my prototype shell script, tentatively titled:
IsOrAreThereOneOrMoreVersionsOfXxxOnThisBoxAndIfSoHowManyAndWhereAreThey.sh
That name can eventually be shortened to just "Hey", so it would be called with "Hey gimp" from the command line. And perhaps I'll set up a mini database to associate things like "GIMP_AppImage-release-2.10.22-withplugins-x86_64.AppImage" to "gimp"; perhaps it could be called the registry, though I think someone else may have already used that name.
yes, which only looks in PATH, type checks functions and aliases, so they are different (and also they depend on the type of the shell too)
What OP wanted is probably a database containing something like this: (name, description, how to start, how to install/uninstall, whatever). Which tool is unavailable at this moment (I think).
What I used to do is to make a small shell script into my ~/bin to run my freshly installed whatever (and therefore all of them will be listed there).
I agree with rnturn that some coding is "undisciplined" though in the case of these sorts of app I'd be more tempted to say it was the design or architecture that was lacking.
I hadn't thought of adding symbolic links when dropping one of these apps on a system;
I think this more or less sums up the problem.
A proper pkging system should always drop either the exe or a symlink into a sane dir ie on usual PATH.
Adding a symlink is a good tidy soln that sticks to the *nix conventions. The only trick is ensuring it gets done at install time.
Distribution: Ubuntu & Mint LTS, Manjaro Rolling; Android
Posts: 242
Original Poster
Rep:
Intriguing - I am familiar with the "standard" xdg-utils [URL="https://www.freedesktop.org/wiki/Software/xdg-utils/"], but the https://github.com/bbidulock/xdg-launch replacement you suggested also has xdg-which and xdg-whereis utilities which might help as well.
Although today and tomorrow will be too busy to play with them, I'll take a look when I get a chance.
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.