linux/Unix可以使用 whereis 这个命令来查找某个特定的程序和命令的二进制文件()、源代码和man手册的位置,貌似现在还能看到软件的配置文件的位置(路径).
命令作用:
查找二进制文件位置,查找软件的配置文件的位置,查找源代码文件位置,查看man手册位置.
语法,基本语法如下:
- whereiscommand
- OR
- whereisprogram
- OR
- whereis[options]program
- OR
- whereis-BMSdirectory-fcommand
whereis 使用举例:
查找 date 命令的 可执行文件、源代码和man手册的位置,输入:
$ whereis date
如何只搜索二进制文件的位置?
使用 -b 参数:$ whereis -b date
如何只搜索man手册的位置?
使用 -m 参数:$ whereis -m date
如何只搜索源代码文件的位置?
使用 -s 参数:$ whereis -s date
问题:whereis -u参数是有问题的,按照man whereis 的说明,-u的就是搜索那些没有二进制文件或者源代码文件或者man手册的文件的,但是实际测试发现,和这毛关系都没有啊.
man手册上的一个例子:
A file is said to be unusual if it does not have one entry of each requested type. Thus the following example, asks for those files in the current directory which have no documentation(意思是搜索当前目录下,没有man文档的文件):
$ whereis -m -u *
我们先cd /bin,然后执行上面的命令,会发现 whereis -m -u * 和 where -m * 结果是一模一样的,-u的功能完全没体现出来,而且与man文档描述的完全不符,因为/bin目录下的文件都是有man文档的,按man文档的意思,结果应该是空的,但是结果却不是空的.
如何限制搜索的路径?
使用下面的参数限制对应的搜索路径:
-B /path/to/dir:限制在指定的目录搜索二进制文件.
-M /path/to/dir:限制在指定的目录搜索man手册文件.
-S /path/to/dir:限制在指定的目录搜索二进制文件.
在使用了-B , -M , -S 任意一个参数时,必须加上 -f 参数,然后指定要搜索的文件名.
实例如下:只在 /bin 目录下搜索 ls 和gcc的:$ whereis -B /bin -f ls gcc
结果如下:
- ls:/bin/ls/usr/share/man/man1/ls.1.gz
- gcc:
可以看到,gcc在/bin目录下搜索二进制文件是没有结果的,说明gcc的二进制文件不在 /bin目录下.
问题:但是,我发现,虽然/bin目录下没有gcc二进制文件,但是使用上面的命令照样有输出,而不是像我翻译的这篇文章那样.
实例2:这也是man手册上的例子,经测试,这里 -u参数还是和man手册上描述的不符合,查找所有/usr/bin目录下的,其man文档不在 /usr/man/man1/,且其源代码文件不在/usr/src/ 的 文件,输入:
- #cd/usr/bin
- #whereis-u-ms-M/usr/man/man1-S/usr/src-f*
- //测试:
- #cd/bin
- #whereis-u-m-M/root-f*
按man手册的意思,这行命令的功能是:查找 所有/bin下,其man文档不在/root的文件,所以应该是有结果输出的,因为/root目录下根本没有任何文件的man手册,可以,惊奇的发现,结果居然是空的.
- whereiscommandoptions
- Fromthewhereis(1)commandmanpage:
- OptionMeaning
- -fDefinesearchscope.
- -bSearchonlybinaries.
- -BDefinebinarieslookuppath.
- -mSearchonlymanualpaths.
- -MDefinemanlookuppath.
- -sSearchonlysourcespath.
- -SDefinesourceslookuppath.
- -uSearchfromunusualenties.
- -VOutputversioninformationandexit.无效的,man文档无此参数
- -hDisplaythishelpandexit.无效的,man文档无此参数
- SEEALSO
- whereis(1)Linux/Unixcommandmanpage
- CategoryListofUnixandLinuxcommands
- FileManagementcat
- NetworkUtilitiesdig•host•ip
- ProcessesManagementbg•chroot•disown•fg•jobs•kill•killall•pwdx•time•pidof•pstree
- Searchingwhereis•which
- UserInformationgroups•id•last•lastcomm•logname•users•w•who•whoami•lid•members
关于whereis 的 -u参数的功能,因为不知道whereis的版本,不好查找对应版本的whereis的源代码,我从网上找了个新版本的whereis的c源代码,明显的发现,whereis使用hard-coded paths.
whereis在git上的代码地址:https://github.com/karelzak/util-linux/blob/master/misc-utils/whereis.c#L96
代码如下:
- /*-
- *Copyright(c)1980TheRegentsoftheUniversityofCalifornia.
- *Allrightsreserved.
- *
- *Redistributionanduseinsourceandbinaryforms,withorwithout
- *modification,arepermittedprovidedthatthefollowingconditions
- *aremet:
- *1.Redistributionsofsourcecodemustretaintheabovecopyright
- *notice,thislistofconditionsandthefollowingdisclaimer.
- *2.Redistributionsinbinaryformmustreproducetheabovecopyright
- *notice,thislistofconditionsandthefollowingdisclaimerinthe
- *documentationand/orothermaterialsprovidedwiththedistribution.
- *3.Alladvertisingmaterialsmentioningfeaturesoruseofthissoftware
- *mustdisplaythefollowingacknowledgement:
- *ThisproductincludessoftwaredevelopedbytheUniversityof
- *California,Berkeleyanditscontributors.
- *4.NeitherthenameoftheUniversitynorthenamesofitscontributors
- *maybeusedtoendorseorpromoteproductsderivedfromthissoftware
- *withoutspecificpriorwrittenpermission.
- *
- *THISSOFTWAREISPROVIDEDBYTHEREGENTSANDCONTRIBUTORS``ASIS''AND
- *ANYEXPRESSORIMPLIEDWARRANTIES,INCLUDING,BUTNOTLIMITEDTO,THE
- *IMPLIEDWARRANTIESOFMERCHANTABILITYANDFITNESSFORAPARTICULARPURPOSE
- *AREDISCLAIMED.INNOEVENTSHALLTHEREGENTSORCONTRIBUTORSBELIABLE
- *FORANYDIRECT,INDIRECT,INCIDENTAL,SPECIAL,EXEMPLARY,ORCONSEQUENTIAL
- *DAMAGES(INCLUDING,BUTNOTLIMITEDTO,PROCUREMENTOFSUBSTITUTEGOODS
- *ORSERVICES;LOSSOFUSE,DATA,ORPROFITS;ORBUSINESSINTERRUPTION)
- *HOWEVERCAUSEDANDONANYTHEORYOFLIABILITY,WHETHERINCONTRACT,STRICT
- *LIABILITY,ORTORT(INCLUDINGNEGLIGENCEOROTHERWISE)ARISINGINANYWAY
- *OUTOFTHEUSEOFTHISSOFTWARE,EVENIFADVISEDOFTHEPOSSIBILITYOF
- *SUCHDAMAGE.
- *
- *1999-02-22ArkadiuszMi?kiewicz<misiek@pld.ORG.PL>
- *-addedNativeLanguageSupport
- *2011-08-12DavidlohrBueso<dave@gnu.org>
- *-added$PATHlookup
- *
- *Copyright(C)2013KarelZak<kzak@redhat.com>
- *2013SamiKerola<kerolasa@iki.fi>
- */
- #include<sys/param.h>
- #include<sys/types.h>
- #include<sys/stat.h>
- #include<dirent.h>
- #include<stdio.h>
- #include<stdlib.h>
- #include<string.h>
- #include<ctype.h>
- #include<assert.h>
- #include"xalloc.h"
- #include"nls.h"
- #include"c.h"
- #include"closestream.h"
- #include"canonicalize.h"
- #include"debug.h"
- UL_DEBUG_DEFINE_MASK(whereis);
- UL_DEBUG_DEFINE_MASKNAMES(whereis)=UL_DEBUG_EMPTY_MASKNAMES;
- #defineWHEREIS_DEBUG_INIT(1<<1)
- #defineWHEREIS_DEBUG_PATH(1<<2)
- #defineWHEREIS_DEBUG_ENV(1<<3)
- #defineWHEREIS_DEBUG_ARGV(1<<4)
- #defineWHEREIS_DEBUG_SEARCH(1<<5)
- #defineWHEREIS_DEBUG_STATIC(1<<6)
- #defineWHEREIS_DEBUG_LIST(1<<7)
- #defineWHEREIS_DEBUG_ALL0xFFFF
- #defineDBG(m,x)__UL_DBG(whereis,WHEREIS_DEBUG_,m,x)
- #defineON_DBG(m,x)__UL_DBG_CALL(whereis,WHEREIS_DEBUG_,m,x)
- staticcharuflag=0;
- /*supportedtypes*/
- enum{
- BIN_DIR=(1<<1),
- MAN_DIR=(1<<2),
- SRC_DIR=(1<<3),
- ALL_DIRS=BIN_DIR|MAN_DIR|SRC_DIR
- };
- /*directories*/
- structwh_dirlist{
- inttype;
- dev_tst_dev;
- ino_tst_ino;
- char*path;
- structwh_dirlist*next;
- };
- staticconstchar*bindirs[]={
- "/usr/bin",
- "/usr/sbin",
- "/usr/lib",
- "/usr/lib64",
- "/bin",
- "/sbin",
- "/etc",
- "/usr/etc",
- "/lib",
- "/lib64",
- "/usr/games",
- "/usr/games/bin",
- "/usr/games/lib",
- "/usr/emacs/etc",
- "/usr/lib/emacs/*/etc",
- "/usr/TeX/bin",
- "/usr/tex/bin",
- "/usr/interviews/bin/LINUX",
- "/usr/X11R6/bin",
- "/usr/X386/bin",
- "/usr/bin/X11",
- "/usr/X11/bin",
- "/usr/X11R5/bin",
- "/usr/local/bin",
- "/usr/local/sbin",
- "/usr/local/etc",
- "/usr/local/lib",
- "/usr/local/games",
- "/usr/local/games/bin",
- "/usr/local/emacs/etc",
- "/usr/local/TeX/bin",
- "/usr/local/tex/bin",
- "/usr/local/bin/X11",
- "/usr/contrib",
- "/usr/hosts",
- "/usr/include",
- "/usr/g++-include",
- "/usr/ucb",
- "/usr/old",
- "/usr/new",
- "/usr/local",
- "/usr/libexec",
- "/usr/share",
- "/opt/*/bin",
- NULL
- };
- staticconstchar*mandirs[]={
- "/usr/man/*",
- "/usr/share/man/*",
- "/usr/X386/man/*",
- "/usr/X11/man/*",
- "/usr/TeX/man/*",
- "/usr/interviews/man/mann",
- "/usr/share/info",
- NULL
- };
- staticconstchar*srcdirs[]={
- "/usr/src/*",
- "/usr/src/lib/libc/*",
- "/usr/src/lib/libc/net/*",
- "/usr/src/ucb/pascal",
- "/usr/src/ucb/pascal/utilities",
- "/usr/src/undoc",
- NULL
- };
- staticvoidwhereis_init_debug(void)
- {
- __UL_INIT_DEBUG(whereis,WHEREIS_DEBUG_,0,WHEREIS_DEBUG);
- }
- staticconstchar*whereis_type_to_name(inttype)
- {
- switch(type){
- caseBIN_DIR:return"bin";
- caseMAN_DIR:return"man";
- caseSRC_DIR:return"src";
- default:return"???";
- }
- }
- staticvoid__attribute__((__noreturn__))usage(FILE*out)
- {
- fputs(USAGE_HEADER,out);
- fprintf(out,_("%s[options]<file>\n"),program_invocation_short_name);
- fputs(USAGE_SEPARATOR,out);
- fputs(_("Locatethebinary,source,andmanual-pagefilesforacommand.\n"),out);
- fputs(USAGE_OPTIONS,out);
- fputs(_("-bsearchonlyforbinaries\n"),out);
- fputs(_("-B<dirs>definebinarieslookuppath\n"),out);
- fputs(_("-msearchonlyformanualsandinfos\n"),out);
- fputs(_("-M<dirs>definemanandinfolookuppath\n"),out);
- fputs(_("-ssearchonlyforsources\n"),out);
- fputs(_("-S<dirs>definesourceslookuppath\n"),out);
- fputs(_("-fterminate<dirs>argumentlist\n"),out);
- fputs(_("-usearchforunusualentries\n"),out);
- fputs(_("-loutputeffectivelookuppaths\n"),out);
- fprintf(out,USAGE_MAN_TAIL("whereis(1)"));
- exit(out==stderr?EXIT_FAILURE:EXIT_SUCCESS);
- }
- staticvoiddirlist_add_dir(structwh_dirlist**ls0,inttype,constchar*dir)
- {
- structstatst;
- structwh_dirlist*prev=NULL,*ls=*ls0;
- if(access(dir,R_OK)!=0)
- return;
- if(stat(dir,&st)!=0||!S_ISDIR(st.st_mode))
- return;
- while(ls){
- if(ls->st_ino==st.st_ino&&
- ls->st_dev==st.st_dev&&
- ls->type==type){
- DBG(LIST,ul_debugobj(*ls0,"ignore(alreadyinlist):%s",dir));
- return;
- }
- prev=ls;
- ls=ls->next;
- }
- ls=xcalloc(1,sizeof(*ls));
- ls->st_ino=st.st_ino;
- ls->st_dev=st.st_dev;
- ls->type=type;
- ls->path=canonicalize_path(dir);
- if(!*ls0)
- *ls0=ls;/*firstinthelist*/
- else{
- assert(prev);
- prev->next=ls;/*addtotheendofthelist*/
- }
- DBG(LIST,ul_debugobj(*ls0,"adddir:%s",ls->path));
- return;
- }
- /*specialcasefor'*'inthepaths*/
- staticvoiddirlist_add_subdir(structwh_dirlist**ls,inttype,constchar*dir)
- {
- charbuf[PATH_MAX],*d;
- DIR*dirp;
- structdirent*dp;
- strncpy(buf,dir,PATH_MAX);
- buf[PATH_MAX-1]='\0';
- d=strchr(buf,'*');
- if(!d)
- return;
- *d=0;
- dirp=opendir(buf);
- if(!dirp)
- return;
- DBG(LIST,ul_debugobj(*ls,"scanningsubdir:%s",dir));
- while((dp=readdir(dirp))!=NULL){
- if(!strcmp(dp->d_name,".")||!strcmp(dp->d_name,".."))
- continue;
- snprintf(d,PATH_MAX-(d-buf),"%s",dp->d_name);
- /*adirdefinitioncanhaveastarinmiddleofpath*/
- strcat(buf,strchr(dir,'*')+1);
- dirlist_add_dir(ls,type,buf);
- }
- closedir(dirp);
- return;
- }
- staticvoidconstruct_dirlist_from_env(constchar*env,
- structwh_dirlist**ls,
- inttype)
- {
- char*key=NULL,*tok=NULL,*pathcp,*path=getenv(env);
- if(!path)
- return;
- pathcp=xstrdup(path);
- DBG(ENV,ul_debugobj(*ls,"construct%sdirlistfrom:%s",
- whereis_type_to_name(type),path));
- for(tok=strtok_r(pathcp,":",&key);tok;
- tok=strtok_r(NULL,":",&key))
- dirlist_add_dir(ls,type,tok);
- free(pathcp);
- return;
- }
- staticvoidconstruct_dirlist_from_argv(structwh_dirlist**ls,
- int*idx,
- intargc,
- char*argv[],
- inttype)
- {
- inti;
- DBG(ARGV,ul_debugobj(*ls,"construct%sdirlistfromargv[%d..]",
- whereis_type_to_name(type),*idx));
- for(i=*idx;i<argc;i++){
- if(*argv[i]=='-')/*endofthelist*/
- break;
- DBG(ARGV,ul_debugobj(*ls,"usingargv[%d]:%s",*idx,argv[*idx]));
- dirlist_add_dir(ls,type,argv[i]);
- *idx=i;
- }
- return;
- }
- staticvoidconstruct_dirlist(structwh_dirlist**ls,
- inttype,
- constchar**paths)
- {
- size_ti;
- DBG(STATIC,ul_debugobj(*ls,"construct%sdirlistfromstaticarray",
- whereis_type_to_name(type)));
- for(i=0;paths[i];i++){
- if(!strchr(paths[i],'*'))
- dirlist_add_dir(ls,type,paths[i]);
- else
- dirlist_add_subdir(ls,type,paths[i]);
- }
- return;
- }
- staticvoidfree_dirlist(structwh_dirlist**ls0,inttype)
- {
- structwh_dirlist*prev=NULL,*next,*ls=*ls0;
- *ls0=NULL;
- DBG(LIST,ul_debugobj(*ls0,"freedirlist"));
- while(ls){
- if(ls->type&type){
- next=ls->next;
- DBG(LIST,ul_debugobj(*ls0,"free:%s",ls->path));
- free(ls->path);
- free(ls);
- ls=next;
- if(prev)
- prev->next=ls;
- }else{
- if(!prev)
- *ls0=ls;/*firstunremoved*/
- prev=ls;
- ls=ls->next;
- }
- }
- return;
- }
- staticintfilename_equal(constchar*cp,constchar*dp)
- {
- inti=strlen(dp);
- DBG(SEARCH,ul_debug("compare'%s'and'%s'",cp,dp));
- if(dp[0]=='s'&&dp[1]=='.'&&filename_equal(cp,dp+2))
- return1;
- if(!strcmp(dp+i-2,".Z"))
- i-=2;
- elseif(!strcmp(dp+i-3,".gz"))
- i-=3;
- elseif(!strcmp(dp+i-3,".xz"))
- i-=3;
- elseif(!strcmp(dp+i-4,".bz2"))
- i-=4;
- while(*cp&&*dp&&*cp==*dp)
- cp++,dp++,i--;
- if(*cp==0&&*dp==0)
- return1;
- while(isdigit(*dp))
- dp++;
- if(*cp==0&&*dp++=='.'){
- --i;
- while(i>0&&*dp)
- if(--i,*dp++=='.')
- return(*dp++=='C'&&*dp++==0);
- return1;
- }
- return0;
- }
- staticvoidfindin(constchar*dir,constchar*pattern,int*count,char**wait)
- {
- DIR*dirp;
- structdirent*dp;
- dirp=opendir(dir);
- if(dirp==NULL)
- return;
- DBG(SEARCH,ul_debug("find'%s'in'%s'",pattern,dir));
- while((dp=readdir(dirp))!=NULL){
- if(!filename_equal(pattern,dp->d_name))
- continue;
- if(uflag&&*count==0)
- xasprintf(wait,"%s/%s",dir,dp->d_name);
- elseif(uflag&&*count==1&&*wait){
- printf("%s:%s%s/%s",pattern,*wait,dir,dp->d_name);
- free(*wait);
- *wait=NULL;
- }else
- printf("%s/%s",dir,dp->d_name);
- ++(*count);
- }
- closedir(dirp);
- return;
- }
- staticvoidlookup(constchar*pattern,structwh_dirlist*ls,intwant)
- {
- charpatbuf[PATH_MAX];
- intcount=0;
- char*wait=NULL,*p;
- /*canonicalizepattern--removepathsuffixetc.*/
- p=strrchr(pattern,'/');
- p=p?p+1:(char*)pattern;
- strncpy(patbuf,p,PATH_MAX);
- patbuf[PATH_MAX-1]='\0';
- DBG(SEARCH,ul_debug("lookupdirsfor'%s'(%s),want:%s%s%s",
- patbuf,pattern,
- want&BIN_DIR?"bin":"",
- want&MAN_DIR?"min":"",
- want&SRC_DIR?"src":""));
- p=strrchr(patbuf,'.');
- if(p)
- *p='\0';
- if(!uflag)
- /*if-unotspecifiedthenwealwaysprintthepattern*/
- printf("%s:",patbuf);
- for(;ls;ls=ls->next){
- if((ls->type&want)&&ls->path)
- findin(ls->path,patbuf,&count,&wait);
- }
- free(wait);
- if(!uflag||(uflag&&count>1))
- putchar('\n');
- return;
- }
- staticvoidlist_dirlist(structwh_dirlist*ls)
- {
- while(ls){
- if(ls->path){
- switch(ls->type){
- caseBIN_DIR:
- printf("bin:");
- break;
- caseMAN_DIR:
- printf("man:");
- break;
- caseSRC_DIR:
- printf("src:");
- break;
- default:
- abort();
- }
- printf("%s\n",ls->path);
- }
- ls=ls->next;
- }
- }
- intmain(intargc,char**argv)
- {
- structwh_dirlist*ls=NULL;
- intwant=ALL_DIRS;
- inti,want_resetable=0;
- setlocale(LC_ALL,"");
- bindtextdomain(PACKAGE,LOCALEDIR);
- textdomain(PACKAGE);
- atexit(close_stdout);
- if(argc==1)
- usage(stderr);
- whereis_init_debug();
- construct_dirlist(&ls,BIN_DIR,bindirs);
- construct_dirlist_from_env("PATH",&ls,BIN_DIR);
- construct_dirlist(&ls,MAN_DIR,mandirs);
- construct_dirlist_from_env("MANPATH",&ls,MAN_DIR);
- construct_dirlist(&ls,SRC_DIR,srcdirs);
- for(i=1;i<argc;i++){
- constchar*arg=argv[i];
- intarg_i=i;
- DBG(ARGV,ul_debug("argv[%d]:%s",i,arg));
- if(*arg!='-'){
- lookup(arg,ls,want);
- /*
- *Thelookupmask("want")iscumulativeandit's
- *resetableonlywhenithasbeenalreadyused.
- *
- *whereis-b-mfoo:'foo'mask=BIN|MAN
- *whereis-bfoobar:'foo'and'bar'mask=BIN|MAN
- *whereis-bfoo-mbar:'foo'mask=BIN;'bar'mask=MAN
- */
- want_resetable=1;
- continue;
- }
- for(++arg;arg&&*arg;arg++){
- DBG(ARGV,ul_debug("arg:%s",arg));
- switch(*arg){
- case'f':
- break;
- case'u':
- uflag=1;
- break;
- case'B':
- if(*(arg+1))
- usage(stderr);
- i++;
- free_dirlist(&ls,BIN_DIR);
- construct_dirlist_from_argv(
- &ls,&i,argc,argv,BIN_DIR);
- break;
- case'M':
- if(*(arg+1))
- usage(stderr);
- i++;
- free_dirlist(&ls,MAN_DIR);
- construct_dirlist_from_argv(
- &ls,&i,argc,argv,MAN_DIR);
- break;
- case'S':
- if(*(arg+1))
- usage(stderr);
- i++;
- free_dirlist(&ls,SRC_DIR);
- construct_dirlist_from_argv(
- &ls,&i,argc,argv,SRC_DIR);
- break;
- case'b':
- if(want_resetable){
- want=ALL_DIRS;
- want_resetable=0;
- }
- want=want==ALL_DIRS?BIN_DIR:want|BIN_DIR;
- break;
- case'm':
- if(want_resetable){
- want=ALL_DIRS;
- want_resetable=0;
- }
- want=want==ALL_DIRS?MAN_DIR:want|MAN_DIR;
- break;
- case's':
- if(want_resetable){
- want=ALL_DIRS;
- want_resetable=0;
- }
- want=want==ALL_DIRS?SRC_DIR:want|SRC_DIR;
- break;
- case'l':
- list_dirlist(ls);
- break;
- case'V':
- printf(UTIL_LINUX_VERSION);
- returnEXIT_SUCCESS;
- case'h':
- usage(stdout);
- default:
- usage(stderr);
- }
- if(arg_i<i)/*movedtothenextargv[]item*/
- break;//phpfensi.com
- }
- }
- free_dirlist(&ls,ALL_DIRS);
- returnEXIT_SUCCESS;
- }
靠,就连代码注释都有错误,懒得折腾了,哥还有事要做,反正 -u 参数实际很少使用的,有兴趣的可以看下这代码.