linux终端cd未找到命令,为什么`which`命令不能用于`cd`?我也找不到`cd`的可执行文件!...
問題描述
我嘗試了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`的可执行文件!...的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 赤伶什么意思
- 下一篇: 深情且专一的网名72个