问题描述

我尝试了which cd,它没有给出路径,而是返回退出代码1(用echo $?检查)。 coreutil cd本身正在工作,所以可执行文件应该在那里,对吧?我还为cd运行了find,但没有显示可执行文件。那怎么实现呢?

更新:

我不知道我是否应该在另一篇文章中提出这个问题,但由于我认为这里很好,我正在扩展(?)帖子……所以答案其实很简单,没有可执行文件 – 因为它是内置 – 但我发现一些内置(Fedora中的bash shell)有可执行文件!所以内置 – >我想,没有可执行文件是不对的?也许答案解释了内置实际上是什么(内置命令?),这实际上是这里的问题,而不是更多地关注cd …之前发布的一些好的链接表明内置不是程序……那么它们是什么?他们是如何工作的?它们只是shell的函数或线程吗?

最佳解决方案

命令cd不能是可执行文件

在shell中,cd用于“进入另一个目录”,或者更正式地用于更改curent工作目录(CWD)。作为外部命令实现它是不可能的:

该目录属于进程

curent工作目录是用于解释相对路径以获取可用于访问文件的完整路径的目录。相对路径在许多地方使用,一个过程中的解释不应影响另一个过程。因此,每个进程都有自己当前的工作目录。

cd是关于更改shell进程的当前工作目录,例如bash。

如果它是一个外部命令,路径中的可执行文件,运行该可执行文件将创建一个具有自己的工作目录的进程,而不会影响当前shell的进程。即使外部命令会改变它的目录,当外部进程退出时,该更改也会消失。

Shell内置命令

因此,为cd的任务运行外部命令是没有意义的。命令cd需要对当前运行的shell进程应用更改。

为此,它是shell的“builtin command”。

内置命令是与外部命令类似的命令,但是在shell中实现(因此cd不是coreutils的一部分)。这允许命令改变shell本身的状态,在这种情况下调用chdir()参见(参见man 2 chdir);

关于which

现在,标题问题的答案很简单:可执行命令which无法告诉我们cd是内置命令,因为可执行命令对内置命令一无所知。

替代type -a

作为which的替代品,您可以使用type -a;它可以看到可执行命令和内置函数;另外,它会看到别名和函数 – 也在shell中实现:

$ type -a cd

cd is a shell builtin

$ type -a type

type is a shell builtin

$ type -a which

which is /usr/bin/which

which is /bin/which

次佳解决方案

cd是一个内置的POSIX-mandated shell:

If a simple command results in a command name and an optional list of arguments, the following actions shall be performed:

If the command name does not contain any slashes, the first successful step in the following sequence shall occur:

If the command name matches the name of a utility listed in the following table, that utility shall be invoked.

cd

Otherwise, the command shall be searched for using the PATH…

虽然这没有明确说明它必须是内置,但规范接着说,在cd的描述中:

Since cd affects the current shell execution environment, it is always provided as a shell regular built-in.

从bash手册:

The following shell builtin commands are inherited from the Bourne Shell. These commands are implemented as specified by the POSIX standard.

cd cd [-L|[-P [-e]]] [directory]

我想你可以想到一个架构,其中cd不一定是内置的。但是,你必须看看内置意味着什么。如果你在shell中编写特殊代码来为某个命令做一些事情,你就会接近内置。你做的越多,只需要内置就越好。

例如,你可以让shell有IPC与子进程通信,并且会有一个cd程序,它会检查目录是否存在以及你是否有权访问它,然后与shell通信以告诉它改变它的目录。但是,您必须检查与您通信的进程是否是子进程(或者只与子进程通信的特殊方式,例如特殊文件描述符,共享内存等),如果进程实际上是运行受信任的cd程序或其他东西。这是一整套蠕虫。

或者您可以使用cd程序进行chdir系统调用,并启动一个新shell,其中所有当前环境变量都应用于新shell,然后在完成时以某种方式终止其父shell。

更糟糕的是,您甚至可以拥有一个系统,其中一个进程可以改变其他进程的环境(我认为从技术上讲,您可以使用调试器来完成此操作)。然而,这样的系统将非常非常脆弱。

您将发现自己添加了越来越多的代码来保护这些方法,而简单地将其作为内置函数则相当简单。

某些东西是可执行文件并不能阻止它成为内置函数。例证:

echo和test

echo和test是POSIX-mandated用途(/bin/echo和/bin/test)。然而,几乎所有流行的 shell 都有内置的echo和test。同样,kill也是内置的,可作为程序使用。其他包括:

sleep(不常见)

time

false

true

printf

但是,在某些情况下,命令不能是内置命令。其中之一是cd。通常,如果未指定完整路径,并且命令名称与内置命令名称匹配,则调用适合该命令的函数。取决于shell,内置的行为和可执行文件的行为可能不同(对于具有wildly differing behaviours的echo,这尤其是个问题。如果您想确定行为,最好使用完整的调用可执行文件路径,并设置像POSIXLY_CORRECT的变量(即使那时没有真正的保证)。

从技术上讲,没有什么可以阻止你提供一个也是一个shell的操作系统,并且每个命令都是内置的。接近这个极端的是单片BusyBox。 BusyBox是一个单独的二进制文件(取决于它所调用的名称)可以表现为任何over 240 programs,包括Almquist Shell(ash)。如果在运行BusyBox ash时取消设置PATH,则仍可访问BusyBox中可用的程序,而无需指定PATH。它们接近于shell内置,除了shell本身是内置于BusyBox的sort-of。

案例研究:Debian Almquist Shell(dash)

如果查看dash源代码,执行线程就是这样的(当然,在使用管道和其他东西时还会涉及其他功能):

main→cmdloop→evaltree→evalcommand

然后,evalcommand使用findcommand来确定命令是什么。如果它是内置的,then:

case CMDBUILTIN:

if (spclbltin > 0 || argc == 0) {

poplocalvars(1);

if (execcmd && argc > 1)

listsetvar(varlist.list, VEXPORT);

}

if (evalbltin(cmdentry.u.cmd, argc, argv, flags)) {

if (exception == EXERROR && spclbltin <= 0) {

FORCEINTON;

break;

cmdentry.u.cmd是struct(struct builtincmd),其成员之一是功能指针,具有典型的main:(int, char **)的特征。 evalbltin函数调用(取决于内置函数是否为eval命令)evalcmd或此函数指针。实际功能在各种源文件中定义。例如,echo是:

int

echocmd(int argc, char **argv)

{

int nonl;

nonl = *++argv ? equal(*argv, "-n") : 0;

argv += nonl;

do {

int c;

if (likely(*argv))

nonl += print_escape_str("%s", NULL, NULL, *argv++);

if (nonl > 0)

break;

c = *argv ? ' ' : '\n';

out1c(c);

} while (*argv);

return 0;

}

本节中源代码的所有链接均为行number-based,因此它们可能会更改,恕不另行通知。

1 POSIX系统具有cd可执行文件。

边注:

在Unix和Linux上有很多优秀的帖子。处理shell行为的Linux。特别是:

If you haven’t noticed a pattern in the questions listed so far, nearly all of them involve Stéphane Chazelas.

第三种解决方案

您找不到cd的可执行文件,因为没有。

cd是shell的内部命令(例如bash)。

第四种方案

来自man which:

which returns the pathnames of the files (or links) which would be executed in the current environment, had its arguments been given as commands in a strictly POSIX-conformant shell. It does this by searching the PATH for executable files matching the names of the arguments. It does not follow symbolic links.

从which的描述可以看出,它只是检查PATH。因此,如果您实施了一些bash function,它将不会显示任何内容。最好使用type命令和which。

例如,在Ubuntu ls命令中别名为ls --color=auto。

$ type ls

ls is aliased to `ls --color=auto'

$ which ls

/bin/ls

如果您实现测试功能hello:

$ function hello() { for i in {1,2,3}; do echo Hello $i;done }

$ which hello

which什么都没有显示。但是type:

$ type hello

hello is a function

hello ()

{

for i in {1,2,3};

do

echo Hello $i;

done

}

在你的情况下:

$ type cd

cd is a shell builtin

这意味着cd是shell builtin,它位于bash内。所有bash builtins在man bash中描述,在SHELL BUILTIN命令中

SHELL BUILTIN COMMANDS

Unless otherwise noted, each builtin command documented in this section

as accepting options preceded by - accepts -- to signify the end of the

options. The :, true, false, and test builtins do not accept options

and do not treat -- specially. The exit, logout, break, continue, let,

and shift builtins accept and process arguments beginning with - with‐

out requiring --. Other builtins that accept arguments but are not

specified as accepting options interpret arguments beginning with - as

invalid options and require -- to prevent this interpretation.

参考资料

linux终端cd未找到命令,为什么`which`命令不能用于`cd`?我也找不到`cd`的可执行文件!...相关推荐

  1. linux开发板显示横向彩虹,给 Linux 终端的输出添加彩虹特效的命令

    原标题:给 Linux 终端的输出添加彩虹特效的命令 正文 如果认为Linux命令行很无聊并且没有任何乐趣,那么您错了,真实的Linux多么有趣和淘气. 在本文,我将介绍一个名为" lolc ...

  2. 5 个用于在 Linux 终端中查找域名 IP 地址的命令

    5 个用于在 Linux 终端中查找域名 IP 地址的命令 本教程介绍了如何在 Linux 终端验证域名或计算机名的 IP 地址.本教程将允许你一次检查多个域.你可能已经使用过这些命令来验证信息.但是 ...

  3. Linux bash: redis-server: 未找到命令

    项目场景: 当你在Linux中安装好了Redis,想启动时,输入redis-server命令,却没办法运行,报redis-server: 未找到命令. 问题描述 Linux安装好了Redis,运行时使 ...

  4. linux中wget未找到命令

    在装数据库的时候发现无法使用wget命令,提示未找到命令,如图所示 那是因为没有安装wget,输入命令:yum -y install wget 如下图所示,wget及其依赖将会被安装 安装完成后就可以 ...

  5. 在 ServiceModel 客户端配置部分中,找不到引用协定“WebServiceSoap”的默认终结点元素。这可能是因为未找到应用程序的配置文件,或者是因为客户端元素找不到与此协定匹配的终结点元素

    在引用WebService后,程序运行到实例化WebService时报错,错误如下: 由于WebService我是在类库里添加的,主程序引用了这个类库,就出现了这个问题. 解决办法: 根据异常信息: ...

  6. linux终端cd未找到命令,Linux cd 命令 command not found cd 命令详解 cd 命令未找到 cd 命令安装 - CommandNotFound ⚡️ 坑否...

    显示行号 | 选择喜欢的代码风格 默认 GitHub Dune LakeSide Plateau Vibrant Blue Eighties Tranquil cd 命令切换用户当前工作目录. cd ...

  7. linux 下orapwd 未找到命令,orapwd命令中entries参数的作用

    orapwd命令中entries参数的作用 作者 blue_stone E-mail: blue_stone@xinhuanet.com Blog: http://bluestone.cublog.c ...

  8. linux 下orapwd 未找到命令,关于orapwd命令entries参数的探究

    今日早上看Oracle官方文档<Administrator's Guide>时,在密码文件章节,关于orapwd命令entries参数的说明如下: This argument specif ...

  9. linux显示mdadm未找到命令,Linux mdadm命令解析

    mdadm命令解析 一,在Linux系统中目前MD(Multiple Devices)虚拟块设备的方式实现软件RAID,利用多个底层的块设备虚拟出一个新的虚拟设备,并且利用条带化(stripping) ...

最新文章

  1. 黄聪:BackGroundWorker解决“线程间操作无效: 从不是创建控件的线程访问它” (C# VS2008)...
  2. LeetCode:226. 翻转二叉树
  3. 关于项目管理的一点体会
  4. C++【EasyX】校园导航系统(阶段性实训项目)
  5. linux命令总结之tr命令
  6. 【iOS】使用storyboard界面跳转报错:unrecognized selector sent to instance 0x7
  7. mybatis mysql upsert_SpringBoot2.3.4+Mybatis+Phoenix操作HBase2.0.6
  8. jieba分词的原理
  9. Java8 Stream(11)List转Map
  10. python中xlsxwriter模块_python xlsxwriter模块的使用
  11. Excel如何将多个工作簿数据合并到一起
  12. 电容或电感的电压_电感基础4——什么是LC电路的“谐振频率”?
  13. mysql group by 命令_MySQL常用命令(八)--GROUP BY、HAVING、SELECT子句的顺序
  14. 【论文笔记】Question Answering with Subgraph Embeddings
  15. 文本相似度 Text Similarity
  16. el-table动态合并单元格
  17. JAVA快递单号查询接口对接第三方快递鸟api接口教程
  18. 电子与通信工程专业毕设选题推荐
  19. 【图解DSA数字签名算法】DSA签名算法的Python实现 | 物联网安全 | 信息安全
  20. 山东大学matlab在哪,山东大学在哪?

热门文章

  1. 识别Java中的代码气味
  2. [MEGA DEAL]完整的Java捆绑包(96%折扣)
  3. java ee cdi_Java EE CDI Producer方法教程
  4. 什么是JAX-RS注释?
  5. 使用JavaSymbolSolver解决Java代码中的方法调用
  6. 将JPA Hibernate与OptaPlanner集成
  7. LongAccumulator和DoubleAccumulator类如何工作?
  8. Maven常见问题和陷阱
  9. 摇篮善良:仅添加包装用于战争
  10. 与詹金斯一起连续交付Heroku