為什麼「whereis」和「which」不顯示指令的位置?

為什麼「whereis」和「which」不顯示指令的位置?

whereis命令喜歡或which不顯示命令位置的原因是什麼?例如,我有 nvm,想知道它位於哪裡,但這些命令都不能幫助我找到二進位。我應該只find在這種情況下使用嗎?

更新

這是長輸出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
}

答案1

which實用程式僅搜尋檔案的現有路徑,因此如果您無法鍵入“nvm”並讓它執行 nvm,則它將無法找到它。

另一方面,whereis搜尋程式的硬編碼路徑清單、其手冊頁及其來源目錄。如果 nvm 不在您的路徑中,則 whereis 可能會找到某些內容,但如果 nvm 不在 whereis 搜尋的硬編碼路徑清單中,則同樣會不成功。

正如您所暗示的,find它是一個更靈活的實用程序,用於搜尋您想要指定的任何類型文件的任何路徑。如果您系統上的任何位置都有 nvm 可執行文件,則可以使用 find 來尋找它,無論它是否在您的系統路徑中。

要研究的第四個選項是locate命令,它使用系統上文件的索引資料庫來快速查找系統上任何位置的文件,透過類似的簡單調用which或whereis,例如locate nvm

答案2

與問題沒有直接關係,但有時which即使文件位於您的路徑上也無法找到文件,並且您可以在 shell 中成功執行該命令。如果您在路徑上使用了 shell 擴展,則可能會發生這種情況:您的 shell 將使用它們,但which也可能不會。

例如,which將無法在此目錄中找到可執行檔(其中 ~ 由 shell 擴展到主目錄): export PATH="$PATH:~/foo/bin"

如果你使用 bash,你不妨養成使用type代替 的習慣which,因為它似乎不存在這個問題。看到這個答案以獲得更多選擇。

答案3

如果您使用curl來安裝nvm(以及可能的其他方法),它會將自身作為一組shell函數安裝在您的主目錄中名為 的隱藏資料夾中.nvm/nvm.sh。由於它不是命令(在其他答案中已解釋),這就是為什麼whereis無法which找到它。請注意,同一目錄有一個 Readme.markdown,其中包含有關 nvm 的大量詳細資訊。

這是您可以透過curl來安裝nvm的腳本: https://raw.githubusercontent.com/creationix/nvm/v0.17.3/install.sh

我遇到了同樣的問題,並透過它揭示了它自己安裝的位置,因此這可能是一種有用的方法,可以找出其他命令實際上不是命令時的位置。

nvm 的作者對 nvm.sh 的工作原理做了很好的解釋:

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

簡而言之,nvm 是 shell 函數的集合,儘管它具有 .sh 副檔名,但實際上並不是 shell 腳本。這就是為什麼它沒有可執行權限(並且不應更改)。要運行它,必須“來源”:

. ~/.nvm/nvm.sh

點是「source」指令的同義詞。取得它可讓檔案中的函數用於目前 shell。例如,如果您需要從 shell 腳本執行 nvm,這會在腳本運行期間開啟新 shell,則您將需要在檔案中取得 nvm,因為否則它將不可用。

答案4

whereis並且which只搜尋特定位置。

man whereis:

whereis 實用程式檢查指定程式的標準二進位目錄,並列印出它找到的任何程式的路徑。

man which:

which 實用程式會取得命令名稱列表,並搜尋實際呼叫這些命令時將執行的每個可執行檔的路徑。

小路指的是PATH環境變數。 (了解更多相關信息

因此,這些實用程式只會尋找位於預設位置之一(例如/bin/usr/local/bin等)的程序,並且只需鍵入命令名稱即可啟動。

如果您安裝npm在其他地方,例如/home/username/bin/npm,而目錄不在您的 中PATH,則不會以這種方式找到它。您需要使用例如find

相關內容