Mengapa 'whereis' dan 'which' tidak menunjukkan lokasi komando kepada saya?

13

Apa alasan mengapa perintah suka whereisatau whichtidak menunjukkan lokasi perintah kepada saya? Misalnya saya punya nvm dan ingin tahu di mana letaknya, tetapi tidak ada dari perintah ini yang membantu saya menemukan biner. Haruskah saya gunakan hanya finddalam kasus ini?

MEMPERBARUI

Berikut ini adalah keluaran panjang dari 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
sumber
@BroSlow itu jenis sumber nvm. Saya tidak membutuhkannya. Saya ingin tahu di mana letaknya
Vitalii Korsakov
Apa? Tipe tidak cukup banyak hal yang sama yang dilakukannya, kecuali akses lebih lokasi (alias, fungsi, dll ...), lebih cepat, lebih portabel, dll ...
@BroSlow, silakan lihat pembaruan
Vitalii Korsakov
Jika perintahnya adalah alias maka Anda dapat menggunakan 'ketik' <perintah Anda> untuk memeriksa alias.
Sagar Jagnade

Jawaban:

5

The whichutilitas hanya mencari jalan yang ada untuk file, jadi jika Anda tidak bisa mengetik "nvm" dan memilikinya berjalan nvm, maka yang tidak akan menemukan itu.

Di sisi lain, whereismencari daftar jalur untuk program, halaman manual, dan direktori sumbernya. Ada kemungkinan bahwa di mana akan menemukan sesuatu jika nvm tidak ada di jalur Anda, tetapi jika nvm tidak ada dalam daftar jalur yang dikodekan dengan hardcode di mana pencarian, itu juga akan gagal.

Seperti yang Anda maksudkan, findadalah utilitas yang jauh lebih fleksibel untuk mencari jalur apa pun yang Anda inginkan untuk semua jenis file yang dapat Anda tentukan. Jika ada nvm yang dapat dieksekusi di mana saja di sistem Anda, find dapat digunakan untuk memburunya, terlepas dari itu berada di jalur sistem Anda.

Opsi keempat untuk dicari adalah locateperintah, yang menggunakan basis data yang diindeks dari file di sistem Anda untuk dengan cepat menemukan file di mana saja di sistem Anda, dengan doa sederhana yang serupa dengan yang atau di mana, misalnyalocate nvm

Jeremy Sturdivant
sumber
whichakan berperilaku seperti ini dengan benar jika Anda menggunakan varian C-shell, seperti cshatau tcsh. Ini dapat bekerja dengan benar di shell lain juga. Namun, di bashdalamnya tidak berfungsi. bashmenggunakan typeperintah sebagai gantinya. Sangat mungkin untuk tidak whichmemberi Anda apa pun bashbahkan ketika seseorang dapat mengetik nvmdan membuatnya berfungsi.
CXJ
3

Jika Anda telah menggunakan curl untuk menginstal nvm (dan mungkin metode lain), itu akan menginstal dirinya sebagai seperangkat fungsi shell di direktori home Anda, di folder tersembunyi bernama .nvm/nvm.sh. Karena ini bukan perintah (dijelaskan dalam jawaban lain) inilah sebabnya whereisdan whichgagal menemukannya. Perhatikan bahwa direktori yang sama memiliki Readme.markdown yang berisi sedikit informasi terperinci tentang nvm.

Ini adalah skrip yang dapat Anda curl untuk menginstal nvm: https://raw.githubusercontent.com/creationix/nvm/v0.17.3/install.sh

Saya memiliki masalah yang sama dan mencari-cari di mana ia menginstal sendiri, jadi itu mungkin metode yang berguna untuk mencari tahu di mana perintah lain hidup ketika mereka sebenarnya bukan perintah.

Ini adalah penjelasan yang bagus oleh penulis nvm tentang cara kerja nvm.sh:

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

Singkatnya, nvm adalah kumpulan fungsi shell, dan meskipun memiliki ekstensi .sh, sebenarnya bukan skrip shell. Inilah sebabnya mengapa ia tidak memiliki izin yang dapat dieksekusi (dan tidak boleh diubah). Untuk menjalankannya, alih-alih harus 'bersumber':

. ~/.nvm/nvm.sh

Titik adalah sinonim untuk perintah 'sumber'. Sumbernya membuat fungsi dalam file tersedia untuk shell saat ini. Jika misalnya Anda perlu menjalankan nvm dari skrip shell, yang membuka shell baru selama durasi skrip, Anda perlu sumber nvm dalam file karena itu tidak akan tersedia jika tidak.

Katharine Osborne
sumber
3

Tidak terkait langsung dengan pertanyaan, tetapi kadang-kadang whichgagal menemukan file meskipun file tersebut ada di jalur Anda, dan Anda dapat berhasil menjalankan perintah di shell Anda. Ini bisa terjadi jika Anda telah menggunakan ekspansi shell di jalur Anda: shell Anda akan menggunakannya tetapi whichmungkin tidak.

Sebagai contoh, whichakan gagal menemukan executable di dalam direktori ini (di mana ~ diperluas oleh shell Anda ke direktori home Anda): export PATH="$PATH:~/foo/bin"

Jika Anda menggunakan bash, Anda sebaiknya membiasakan diri menggunakan typealih-alih which, karena sepertinya tidak memiliki masalah ini. Lihat jawaban ini untuk lebih banyak alternatif.

Patogen
sumber
Ini penting bagi siapa saja yang berasal dari latar belakang cshatau tcsh. Saya digigit oleh bashkekhasan ini hampir setiap kali saya gunakan which.
CXJ
1

Jika nvmperintah Anda sebenarnya adalah fungsi alias atau fungsi shell, whichakan mengidentifikasinya hanya jika Anda menggunakan opsi yang sesuai (misalnya, --read-aliasatau --read-functions; lihat which(1)), dan whereisakan sama sekali tidak berguna.

Scott
sumber
0

whereisdan whichhanya mencari lokasi tertentu.

man whereis:

Utilitas whereis memeriksa direktori biner standar untuk program yang ditentukan, mencetak jalur apa pun yang ditemukannya.

man which:

Utilitas mana yang mengambil daftar nama perintah dan mencari path untuk setiap file yang dapat dieksekusi yang akan dijalankan seandainya perintah ini benar-benar dipanggil.

Path merujuk ke PATHvariabel lingkungan. ( Baca lebih lanjut tentang itu )

Jadi utilitas ini hanya akan menemukan program yang ada di salah satu lokasi default (misalnya /bin, /usr/local/bindll.) Dan dapat diluncurkan hanya dengan mengetikkan nama perintah.

Jika Anda menginstal di npmtempat lain, misalnya /home/username/bin/npm, dan direktori itu tidak ada di Anda PATH, itu tidak akan ditemukan dengan cara ini. Anda harus menggunakan mis find.

Daniel Beck
sumber
1
Saya percaya bahwa nvmdi PATH karena saya dapat mengakses perintah ini dari direktori mana pun
Vitalii Korsakov
whichdapat gagal menemukan hal-hal di jalan dalam beberapa kasus saat menggunakan bash. Lihat jawaban @ Pathogen di atas.
CXJ