什么是`Cd`命令?

May*_*nty 5 macos bash freebsd

我正在编写一些代码,通过命令行浏览我的计算机(OSX 10.11.6),就像我一直这样,我写错了!(Bum-Bum-BUUUUM!)而不是输入:

cd USB
Run Code Online (Sandbox Code Playgroud)

我打字了

Cd USB
Run Code Online (Sandbox Code Playgroud)

什么都没发生,但它没有注册为无效命令.对此感到困惑,我做了一些调查:我检查了man条目.没有入场券.我发现源文件(/usr/bin/Cd)使用which Cd,然后cat编辑它:

#!/bin/sh
# $FreeBSD: src/usr.bin/alias/generic.sh,v 1.2 2005/10/24 22:32:19 cperciva Exp $
# This file is in the public domain.
builtin `echo ${0##*/} | tr \[:upper:] \[:lower:]` ${1+"$@"}
Run Code Online (Sandbox Code Playgroud)

这是什么,为什么会在这里?它与freeBSD有什么关系?

任何帮助都会很棒,谢谢!

mkl*_*nt0 8

默认情况下, macOS使用不区分大小写的文件系统[1] ,这有时会产生误导:

which Cd是有效相同which cdwhich CD在返回(有效地)相同的文件路径的条款.

令人困惑的是,即使所有3个命令都引用同一个文件,它们也会以保持大小写的方式执行此操作,误导性地表明文件名的实际情况是您指定的任何内容.

作为一种解决方法,如果使用globbing(文件名扩展),则可以看到文件名的真实情况:

$ ls "$(which Cd)"*  # could match additional files, but the one of interest is among them
/usr/bin/cd  # true case of the filename
Run Code Online (Sandbox Code Playgroud)

Bash(macOS默认shell)在内部区分大小写.也就是说,它识别cd为builtincd(其内置的目录更改命令).

相比之下,由于案例的不同,它不承认Cd这一点.

鉴于它不能识别Cd为内置函数,它会寻找一个外部实用程序(在$PATH)中,就在它找到时/usr/bin/cd.


/usr/bin/cd实现为shell脚本,这通常是无用的,因为作为外部实用程序它不会影响shell的状态,因此它只是静静地忽略了它更改目录的尝试.
(Keith Thompson在评论中指出,您可以使用它作为测试是否可以更改给定目录,因为脚本的退出代码将反映出来).

Matt的回答提供了将脚本包含在FreeBSD和OSX中的历史(主要基于FreeBSD),但值得仔细研究一下这个理由(强调我的):

POSIX规范:

但是,所有标准实用程序,包括表中的常规内置函数,而不是特殊内置实用程序中描述的特殊内置函数,都应以某种方式实现,以便可以通过exec系列访问它们.函数在POSIX.1-2008的系统接口卷中定义,并且可以由需要它的那些标准实用程序直接调用(env,find,nice,nohup,time,xargs).

从本质上讲,上述意思是:常规内置函数必须(也)可以独立调用,作为可执行文件(无论是脚本还是二进制文件),就像shell中的内置函数一样.

引用的常规内置表包含以下实用程序:

alias bg cd command false fc fg getopts jobs kill newgrp pwd read true umask unalias wait

注意:根据定义,特殊的内置实用程序仅限shell-internal,它们的行为与常规内置实用程序不同.

因此,正式 POSIX兼容的操作系统确实必须提供cd外部工具.

同时,POSIX规范.确实意识到这些常规内置插件中的至少一些 - 特别是cd- 仅作为内置有意义:

"由于cd影响了当前的shell执行环境,因此它总是作为常规内置的shell提供. " - http://pubs.opengroup.org/onlinepubs/9699919799/utilities/cd.html

在列出的常规内置实用程序中,有些作为内置实用程序外部实用程序都有意义:

例如,kill需要内置以杀死作业(这是一个shell 内部概念),但它也可用作外部实用程序,以便通过PID终止进程.

但是,在列出的常规内置实用程序中,以下内容永远不会外部实用程序那样有意义,据我所知,如果您不同意 ,请告诉我,即使POSIX强制要求它们存在:

alias bg cd command fc fg getopts jobs read umask unalias

Matt提供帮助完成清单的提示; 他还指出hash内置的,即使它不是POSIX实用程序,也有一个毫无意义的脚本实现.


[1]正如Dave Newton在评论中指出的那样,可以区分大小写的方式格式化HFS +(macOS文件系统)(即使大多数人坚持使用不区分大小写的默认值).根据Dave链接的答案,以下命令将告诉您macOS文件系统是否不区分大小写:
diskutil info / | grep -iq '^\s*Name.*case-sensitive*' && echo "case-SENSITIVE" || echo "case-INsensitive"

  • OSX区分大小写取决于格式,例如http://apple.stackexchange.com/a/22304 (2认同)