Pourquoi «whereis» et «which» ne me montrent pas l'emplacement de la commande?

13

Quelles sont les raisons pour lesquelles les commandes aiment whereisou whichne me montrent pas l'emplacement de la commande? Par exemple, j'ai nvm et je veux savoir où il se trouve, mais aucune de ces commandes ne m'aide à trouver le binaire. Dois-je utiliser uniquement finddans ce cas?

METTRE À JOUR

Voici une longue sortie de type nvm

$ type nvm
nvm is a function
nvm ()
{
    if [ $# -lt 1 ]; then
        nvm help;
        return;
    fi;
    local uname="$(uname -a)";
    local os=;
    local arch="$(uname -m)";
    case "$uname" in
        Linux\ *)
            os=linux
        ;;
        Darwin\ *)
            os=darwin
        ;;
        SunOS\ *)
            os=sunos
        ;;
        FreeBSD\ *)
            os=freebsd
        ;;
    esac;
    case "$uname" in
        *x86_64*)
            arch=x64
        ;;
        *i*86*)
            arch=x86
        ;;
        *armv6l*)
            arch=arm-pi
        ;;
    esac;
    local VERSION;
    local ADDITIONAL_PARAMETERS;
    case $1 in
        "help")
            echo;
            echo "Node Version Manager";
            echo;
            echo "Usage:";
            echo "    nvm help                    Show this message";
            echo "    nvm install [-s] <version>  Download and install a <version>, [-s] from source";
            echo "    nvm uninstall <version>     Uninstall a version";
            echo "    nvm use <version>           Modify PATH to use <version>";
            echo "    nvm run <version> [<args>]  Run <version> with <args> as arguments";
            echo "    nvm current                 Display currently activated version";
            echo "    nvm ls                      List installed versions";
            echo "    nvm ls <version>            List versions matching a given description";
            echo "    nvm ls-remote               List remote versions available for install";
            echo "    nvm deactivate              Undo effects of NVM on current shell";
            echo "    nvm alias [<pattern>]       Show all aliases beginning with <pattern>";
            echo "    nvm alias <name> <version>  Set an alias named <name> pointing to <version>";
            echo "    nvm unalias <name>          Deletes the alias named <name>";
            echo "    nvm copy-packages <version> Install global NPM packages contained in <version> to current version";
            echo;
            echo "Example:";
            echo "    nvm install v0.10.24        Install a specific version number";
            echo "    nvm use 0.10                Use the latest available 0.10.x release";
            echo "    nvm run 0.10.24 myApp.js    Run myApp.js using node v0.10.24";
            echo "    nvm alias default 0.10.24   Set default node version on a shell";
            echo;
            echo "Note:";
            echo "    to remove, delete or uninstall nvm - just remove ~/.nvm, ~/.npm and ~/.bower folders";
            echo
        ;;
        "install")
            local binavail;
            local t;
            local url;
            local sum;
            local tarball;
            local shasum='shasum';
            local nobinary;
            if ! has "curl"; then
                echo 'NVM Needs curl to proceed.' 1>&2;
            fi;
            if ! has "shasum"; then
                shasum='sha1sum';
            fi;
            if [ $# -lt 2 ]; then
                nvm help;
                return;
            fi;
            shift;
            nobinary=0;
            if [ "$1" = "-s" ]; then
                nobinary=1;
                shift;
            fi;
            if [ "$os" = "freebsd" ]; then
                nobinary=1;
            fi;
            VERSION=`nvm_remote_version $1`;
            ADDITIONAL_PARAMETERS='';
            shift;
            while [ $# -ne 0 ]; do
                ADDITIONAL_PARAMETERS="$ADDITIONAL_PARAMETERS $1";
                shift;
            done;
            [ -d "$NVM_DIR/$VERSION" ] && echo "$VERSION is already installed." && return;
            if [ $nobinary -ne 1 ]; then
                if [ -n "$os" ]; then
                    binavail=;
                    case "$VERSION" in
                        v0.8.[012345])
                            binavail=0
                        ;;
                        v0.[1234567].*)
                            binavail=0
                        ;;
                        *)
                            binavail=1
                        ;;
                    esac;
                    if [ $binavail -eq 1 ]; then
                        t="$VERSION-$os-$arch";
                        url="http://nodejs.org/dist/$VERSION/node-${t}.tar.gz";
                        sum=`curl -s http://nodejs.org/dist/$VERSION/SHASUMS.txt | \grep node-${t}.tar.gz | awk '{print $1}'`;
                        local tmpdir="$NVM_DIR/bin/node-${t}";
                        local tmptarball="$tmpdir/node-${t}.tar.gz";
                        if ( mkdir -p "$tmpdir" && curl -L -C - --progress-bar $url -o "$tmptarball" && nvm_checksum `${shasum} "$tmptarball" | awk '{print $1}'` $sum && tar -xzf "$tmptarball" -C "$tmpdir" --strip-components 1 && rm -f "$tmptarball" && mv "$tmpdir" "$NVM_DIR/$VERSION" ); then
                            nvm use $VERSION;
                            return;
                        else
                            echo "Binary download failed, trying source." 1>&2;
                            rm -rf "$tmptarball" "$tmpdir";
                        fi;
                    fi;
                fi;
            fi;
            echo "Additional options while compiling: $ADDITIONAL_PARAMETERS";
            tarball='';
            sum='';
            make='make';
            if [ "$os" = "freebsd" ]; then
                make='gmake';
            fi;
            local tmpdir="$NVM_DIR/src";
            local tmptarball="$tmpdir/node-$VERSION.tar.gz";
            if [ "`curl -Is "http://nodejs.org/dist/$VERSION/node-$VERSION.tar.gz" | \grep '200 OK'`" != '' ]; then
                tarball="http://nodejs.org/dist/$VERSION/node-$VERSION.tar.gz";
                sum=`curl -s http://nodejs.org/dist/$VERSION/SHASUMS.txt | \grep node-$VERSION.tar.gz | awk '{print $1}'`;
            else
                if [ "`curl -Is "http://nodejs.org/dist/node-$VERSION.tar.gz" | \grep '200 OK'`" != '' ]; then
                    tarball="http://nodejs.org/dist/node-$VERSION.tar.gz";
                fi;
            fi;
            if ( [ ! -z $tarball ] && mkdir -p "$tmpdir" && curl -L --progress-bar $tarball -o "$tmptarball" && if [ "$sum" = "" ]; then
                :;
            else
                nvm_checksum `${shasum} "$tmptarball" | awk '{print $1}'` $sum;
            fi && tar -xzf "$tmptarball" -C "$tmpdir" && cd "$tmpdir/node-$VERSION" && ./configure --prefix="$NVM_DIR/$VERSION" $ADDITIONAL_PARAMETERS && $make && rm -f "$NVM_DIR/$VERSION" 2> /dev/null && $make install ); then
                nvm use $VERSION;
                if ! has "npm"; then
                    echo "Installing npm...";
                    if [[ "`expr match $VERSION '\(^v0\.1\.\)'`" != '' ]]; then
                        echo "npm requires node v0.2.3 or higher";
                    else
                        if [[ "`expr match $VERSION '\(^v0\.2\.\)'`" != '' ]]; then
                            if [[ "`expr match $VERSION '\(^v0\.2\.[0-2]$\)'`" != '' ]]; then
                                echo "npm requires node v0.2.3 or higher";
                            else
                                curl https://npmjs.org/install.sh | clean=yes npm_install=0.2.19 sh;
                            fi;
                        else
                            curl https://npmjs.org/install.sh | clean=yes sh;
                        fi;
                    fi;
                fi;
            else
                echo "nvm: install $VERSION failed!";
                return 1;
            fi
        ;;
        "uninstall")
            [ $# -ne 2 ] && nvm help && return;
            if [[ $2 == `nvm_version` ]]; then
                echo "nvm: Cannot uninstall currently-active node version, $2.";
                return 1;
            fi;
            VERSION=`nvm_version $2`;
            if [ ! -d $NVM_DIR/$VERSION ]; then
                echo "$VERSION version is not installed...";
                return;
            fi;
            t="$VERSION-$os-$arch";
            rm -rf "$NVM_DIR/src/node-$VERSION" "$NVM_DIR/src/node-$VERSION.tar.gz" "$NVM_DIR/bin/node-${t}" "$NVM_DIR/bin/node-${t}.tar.gz" "$NVM_DIR/$VERSION" 2> /dev/null;
            echo "Uninstalled node $VERSION";
            for A in `\grep -l $VERSION $NVM_DIR/alias/* 2>/dev/null`;
            do
                nvm unalias `basename $A`;
            done
        ;;
        "deactivate")
            if [[ $PATH == *$NVM_DIR/*/bin* ]]; then
                export PATH=${PATH%$NVM_DIR/*/bin*}${PATH#*$NVM_DIR/*/bin:};
                hash -r;
                echo "$NVM_DIR/*/bin removed from \$PATH";
            else
                echo "Could not find $NVM_DIR/*/bin in \$PATH";
            fi;
            if [[ $MANPATH == *$NVM_DIR/*/share/man* ]]; then
                export MANPATH=${MANPATH%$NVM_DIR/*/share/man*}${MANPATH#*$NVM_DIR/*/share/man:};
                echo "$NVM_DIR/*/share/man removed from \$MANPATH";
            else
                echo "Could not find $NVM_DIR/*/share/man in \$MANPATH";
            fi;
            if [[ $NODE_PATH == *$NVM_DIR/*/lib/node_modules* ]]; then
                export NODE_PATH=${NODE_PATH%$NVM_DIR/*/lib/node_modules*}${NODE_PATH#*$NVM_DIR/*/lib/node_modules:};
                echo "$NVM_DIR/*/lib/node_modules removed from \$NODE_PATH";
            else
                echo "Could not find $NVM_DIR/*/lib/node_modules in \$NODE_PATH";
            fi
        ;;
        "use")
            if [ $# -eq 0 ]; then
                nvm help;
                return;
            fi;
            if [ $# -eq 1 ]; then
                rc_nvm_version;
                if [ ! -z $RC_VERSION ]; then
                    VERSION=`nvm_version $RC_VERSION`;
                fi;
            else
                VERSION=`nvm_version $2`;
            fi;
            if [ -z $VERSION ]; then
                nvm help;
                return;
            fi;
            if [ -z $VERSION ]; then
                VERSION=`nvm_version $2`;
            fi;
            if [ ! -d "$NVM_DIR/$VERSION" ]; then
                echo "$VERSION version is not installed yet";
                return 1;
            fi;
            if [[ $PATH == *$NVM_DIR/*/bin* ]]; then
                PATH=${PATH%$NVM_DIR/*/bin*}$NVM_DIR/$VERSION/bin${PATH#*$NVM_DIR/*/bin};
            else
                PATH="$NVM_DIR/$VERSION/bin:$PATH";
            fi;
            if [ -z "$MANPATH" ]; then
                MANPATH=$(manpath);
            fi;
            MANPATH=${MANPATH#*$NVM_DIR/*/man:};
            if [[ $MANPATH == *$NVM_DIR/*/share/man* ]]; then
                MANPATH=${MANPATH%$NVM_DIR/*/share/man*}$NVM_DIR/$VERSION/share/man${MANPATH#*$NVM_DIR/*/share/man};
            else
                MANPATH="$NVM_DIR/$VERSION/share/man:$MANPATH";
            fi;
            if [[ $NODE_PATH == *$NVM_DIR/*/lib/node_modules* ]]; then
                NODE_PATH=${NODE_PATH%$NVM_DIR/*/lib/node_modules*}$NVM_DIR/$VERSION/lib/node_modules${NODE_PATH#*$NVM_DIR/*/lib/node_modules};
            else
                NODE_PATH="$NVM_DIR/$VERSION/lib/node_modules:$NODE_PATH";
            fi;
            export PATH;
            hash -r;
            export MANPATH;
            export NODE_PATH;
            export NVM_PATH="$NVM_DIR/$VERSION/lib/node";
            export NVM_BIN="$NVM_DIR/$VERSION/bin";
            echo "Now using node $VERSION"
        ;;
        "run")
            if [ $# -lt 2 ]; then
                nvm help;
                return;
            fi;
            VERSION=`nvm_version $2`;
            if [ ! -d $NVM_DIR/$VERSION ]; then
                echo "$VERSION version is not installed yet";
                return;
            fi;
            if [[ $NODE_PATH == *$NVM_DIR/*/lib/node_modules* ]]; then
                RUN_NODE_PATH=${NODE_PATH%$NVM_DIR/*/lib/node_modules*}$NVM_DIR/$VERSION/lib/node_modules${NODE_PATH#*$NVM_DIR/*/lib/node_modules};
            else
                RUN_NODE_PATH="$NVM_DIR/$VERSION/lib/node_modules:$NODE_PATH";
            fi;
            echo "Running node $VERSION";
            NODE_PATH=$RUN_NODE_PATH $NVM_DIR/$VERSION/bin/node "${@:3}"
        ;;
        "ls" | "list")
            print_versions "`nvm_ls $2`";
            if [ $# -eq 1 ]; then
                echo -ne "current: \t";
                nvm_version current;
                nvm alias;
            fi;
            return
        ;;
        "ls-remote" | "list-remote")
            print_versions "`nvm_ls_remote $2`";
            return
        ;;
        "current")
            echo -ne "current: \t";
            nvm_version current
        ;;
        "alias")
            mkdir -p $NVM_DIR/alias;
            if [ $# -le 2 ]; then
                for ALIAS in $(nvm_set_nullglob; echo $NVM_DIR/alias/$2* );
                do
                    DEST=`cat $ALIAS`;
                    VERSION=`nvm_version $DEST`;
                    if [ "$DEST" = "$VERSION" ]; then
                        echo "$(basename $ALIAS) -> $DEST";
                    else
                        echo "$(basename $ALIAS) -> $DEST (-> $VERSION)";
                    fi;
                done;
                return;
            fi;
            if [ ! "$3" ]; then
                rm -f $NVM_DIR/alias/$2;
                echo "$2 -> *poof*";
                return;
            fi;
            mkdir -p $NVM_DIR/alias;
            VERSION=`nvm_version $3`;
            if [ $? -ne 0 ]; then
                echo "! WARNING: Version '$3' does not exist." 1>&2;
            fi;
            echo $3 > "$NVM_DIR/alias/$2";
            if [ ! "$3" = "$VERSION" ]; then
                echo "$2 -> $3 (-> $VERSION)";
            else
                echo "$2 -> $3";
            fi
        ;;
        "unalias")
            mkdir -p $NVM_DIR/alias;
            [ $# -ne 2 ] && nvm help && return;
            [ ! -f $NVM_DIR/alias/$2 ] && echo "Alias $2 doesn't exist!" && return;
            rm -f $NVM_DIR/alias/$2;
            echo "Deleted alias $2"
        ;;
        "copy-packages")
            if [ $# -ne 2 ]; then
                nvm help;
                return;
            fi;
            local VERSION=`nvm_version $2`;
            local ROOT=`(nvm use $VERSION && npm -g root) | tail -n1`;
            local ROOTDEPTH=$((`echo $ROOT | sed 's/[^\/]//g'|wc -m` -1));
            local INSTALLS;
            INSTALLS=(`nvm use $VERSION > /dev/null && npm -g -p ll | \grep "$ROOT\/[^/]\+$" | cut -d '/' -f $(($ROOTDEPTH + 2)) | cut -d ":" -f 2 | \grep -v npm | tr "\n" " "`);
            npm install -g ${INSTALLS[@]}
        ;;
        "clear-cache")
            rm -f $NVM_DIR/v* 2> /dev/null;
            echo "Cache cleared."
        ;;
        "version")
            print_versions "`nvm_version $2`"
        ;;
        *)
            nvm help
        ;;
    esac
}
Vitalii Korsakov
la source
@BroSlow dont il saisit la source nvm. Je n'en ai pas besoin. Je veux savoir où il se trouve
Vitalii Korsakov
Quelle? type fait à peu près la même chose qui , sauf qu'il accède à plus d'emplacements (alias, fonctions, etc ...), est plus rapide, plus portable, etc ...
@BroSlow voir la mise à jour s'il vous plaît
Vitalii Korsakov
Si la commande est un alias, vous pouvez utiliser 'type' <votre commande> pour vérifier l'alias.
Sagar Jagnade

Réponses:

5

L' whichutilitaire recherche uniquement les fichiers dans votre chemin existant, donc si vous ne pouvez pas taper "nvm" et le faire exécuter nvm, alors qui ne le trouvera pas.

D'un autre côté, whereisrecherche une liste codée en dur de chemins pour le programme, sa page de manuel et son répertoire source. Il est possible que whereis trouve quelque chose si nvm ne se trouve pas dans votre chemin, mais si nvm ne figure pas dans la liste codée en dur des chemins dans lesquels il recherche, il échouera également.

Comme vous l'impliquez, findest un utilitaire beaucoup plus flexible pour rechercher n'importe quel chemin que vous désirez pour tout type de fichier que vous pouvez spécifier. S'il existe un exécutable nvm n'importe où sur votre système, find peut être utilisé pour le rechercher, qu'il se trouve dans votre chemin d'accès système.

Une quatrième option à examiner serait la locatecommande, qui utilise une base de données indexée de fichiers sur votre système pour trouver rapidement un fichier n'importe où sur votre système, avec une invocation tout aussi simple vers laquelle ou où, par exemplelocate nvm

Jeremy Sturdivant
la source
whichse comportera correctement de cette façon si vous utilisez une variante du shell C, telle que cshou tcsh. Il peut également fonctionner correctement dans d'autres coquilles. Cependant, bashcela ne fonctionne pas. bashutilise la typecommande à la place. Il est parfaitement possible de whichne rien vous donner bashmême quand on peut taper nvmet le faire fonctionner.
CXJ
3

Si vous avez utilisé curl pour installer nvm (et éventuellement d'autres méthodes), il s'installera comme un ensemble de fonctions shell dans votre répertoire personnel, dans un dossier caché appelé .nvm/nvm.sh. Comme ce n'est pas une commande (expliquée dans les autres réponses), c'est pourquoi whereiset whichne la trouve pas. Notez que le même répertoire a un fichier Readme.markdown qui contient pas mal d'informations détaillées sur nvm.

Voici le script que vous pouvez utiliser pour installer nvm: https://raw.githubusercontent.com/creationix/nvm/v0.17.3/install.sh

J'ai eu le même problème et en fouillant, cela a révélé où il s'installait, ce qui pourrait être une méthode utile pour savoir où vivent les autres commandes alors qu'elles ne sont pas réellement des commandes.

Voici une excellente explication de l'auteur de nvm sur le fonctionnement de nvm.sh:

https://github.com/creationix/nvm/issues/521

En bref, nvm est une collection de fonctions shell, et même s'il a l'extension .sh, il ne s'agit pas en fait d'un script shell. C'est pourquoi il ne dispose pas d'autorisations exécutables (et ne doit pas être modifié). Pour l'exécuter, il doit plutôt être «sourcé»:

. ~/.nvm/nvm.sh

Le point est synonyme de la commande «source». Le sourcing rend les fonctions du fichier disponibles pour le shell courant. Si, par exemple, vous devez exécuter nvm à partir d'un script shell, ce qui ouvre un nouveau shell pour la durée du script, vous devrez source nvm dans le fichier car il ne sera pas disponible autrement.

Katharine Osborne
la source
3

Pas directement lié à la question, mais whichéchoue parfois à trouver un fichier même s'il se trouve sur votre chemin, et vous pouvez exécuter la commande avec succès dans votre shell. Cela peut se produire si vous avez utilisé des extensions de shell sur votre chemin: votre shell les utilisera, mais whichpeut-être pas.

Par exemple, whichne trouvera pas d'exécutables dans ce répertoire (où ~ est développé par votre shell dans votre répertoire personnel): export PATH="$PATH:~/foo/bin"

Si vous utilisez bash, vous pourriez aussi bien prendre l'habitude d'utiliser à la typeplace de which, car il ne semble pas avoir ce problème. Voir cette réponse pour plus d'alternatives.

Agent pathogène
la source
Ceci est important pour quiconque vient d'un cshou d' un tcsharrière - plan. Je suis mordu par cette bashparticularité presque chaque fois que j'utilise which.
CXJ
1

Si votre nvmcommande est en fait un alias ou une fonction shell, whichne l'identifiera que si vous utilisez une option appropriée (par exemple, --read-aliasou --read-functions; voir which(1)), et whereissera complètement inutile.

Scott
la source
0

whereiset whichrechercher uniquement des emplacements spécifiques.

man whereis:

L'utilitaire whereis vérifie les répertoires binaires standard pour les programmes spécifiés, en imprimant les chemins de tous ceux qu'il trouve.

man which:

L'utilitaire which prend une liste de noms de commandes et recherche le chemin de chaque fichier exécutable qui serait exécuté si ces commandes avaient été effectivement appelées.

Le chemin fait référence à la PATHvariable d'environnement. ( En savoir plus )

Ainsi, ces utilitaires ne trouveront que les programmes qui se trouvent dans l'un des emplacements par défaut (par exemple /bin, /usr/local/binetc.) et pourraient être lancés en tapant simplement le nom de la commande.

Si vous avez installé npmailleurs, par exemple /home/username/bin/npm, et que ce répertoire n'est pas dans votre PATH, il ne sera pas trouvé de cette façon. Vous devrez utiliser par exemple find.

Daniel Beck
la source
1
Je crois que nvmdans le CHEMIN puisque je peux accéder à cette commande depuis n'importe quel répertoire
Vitalii Korsakov
whichpeut ne pas trouver des éléments dans le chemin d'accès dans certains cas lors de l'utilisation bash. Voir la réponse de @ Pathogen ci-dessus.
CXJ