假设我位于控制台的子文件夹中,该子文件夹是符号链接(软)文件夹的子文件夹(或孙文件夹等)。
从子文件夹中,如果我ls -la
什么都不做,则表明所有文件都位于符号链接文件夹内。
我怎么知道呢?目前,我必须转到父文件夹才能知道这一点。
但这意味着通过测试错误查找,测试所有文件夹的层次结构,直到到达父级(链接)。
答案1
您通过某些符号链接导航到当前工作目录的事实仅由您的 shell(即 Bash)跟踪。引导您到达此处的路径称为逻辑路径,它可以包含目录组件,这些目录组件实际上是目录的符号链接。解析完所有符号链接后的路径称为物理路径。
一种既不是您当前的 Bash 也不是其任何内置工具的工具,当它在 shell 的当前工作目录中作为单独的进程生成时,它自然知道该目录的物理路径,因为物理路径是操作系统的路径与进程关联(/proc/self/cwd
对于进程)。该工具可以通过检查PWD
其环境中的变量或使用任何检查变量的工具来了解逻辑路径。变量的值来自您的 Bash。
cd
在 Bash 中,内置函数pwd
可以在物理或逻辑路径上操作,请参阅这个答案。pwd
这不是内置的(例如/usr/bin/pwd
)只能告诉您逻辑路径,因为它检查PWD
其环境中的变量。在符号链接目录中比较这些:
$ env pwd -L
/logical/path
$ env pwd -P
/physical/path
$ env --unset=PWD pwd -L
/physical/path
请注意,所有这些pwd
都不是内置的;env
它本身不是 shell 内置程序,它只能运行pwd
可执行文件,不能运行内置程序。通过从PWD
环境中移除,我们使pwd -L
行为变得像pwd -P
。
ls
不关心PWD
环境。物理路径和逻辑路径之间可能存在的差异与所做的事情无关ls
。您可能认为它应该有所不同。在问题的第一个版本中,您错误地假设符号链接目录中的所有文件都是符号链接;有了这个假设,很容易进一步假设ls
隐藏了这个事实。事实上,ls
在某些(物理)目录中,无论什么逻辑路径引导您的 shell 到该目录,都以相同的方式工作。
pwd -P
您可以通过将 的输出与 的输出进行比较pwd -L
(或直接与)来检测物理路径和逻辑路径之间的差异$PWD
。让我们构建一个基本警告ls
:
function ls (
p="$(pwd -P)"
command ls "$@"
[ "$p" != "$PWD" ] && >&2 printf 'ls: warning: ./ -> %s/\n' "$p"
)
我使用了一个函数,而不是别名,因为alias ls='ls --color=auto'
它很常见,我不想破坏它;还因为别名不适用于此。别名极有可能存在,使得语法function ls …
比可移植的更好ls () …
(后者触发别名)。
这个基本功能并不完善。ls /some/other/dir
永远不会警告您/some/other/dir
,它会警告您./
(如果符号链接),尽管./
在这种情况下无关紧要。
无论如何,“我怎么知道我所在的子目录是符号链接目录的(孙…)子目录?”的答案?是:
[ "$(pwd -P)" != "$PWD" ]
答案2
我添加$(pwd -P)
到我的 bash 提示符中;这给出了真实的文件夹名称而不是符号链接的名称。ls
据我所知,没有任何命令开关可以给你你想要的东西。但至少更改提示可以让您知道当前所在的确切位置。
答案3
基于@ajgringo619
这解决了它:
# includes complete left path
alias ll2='if [[ $(diff <(ls "$PWD" | sed "s|.*|$(ls -d "$PWD/")&|g") <(ls -d "$(pwd -P)/"*) | wc -l) == "0" ]]; then ls -l; else paste -d " -> " <(ls "$PWD" | sed "s|.*|$(ls -d "$PWD/")&|g") /dev/null /dev/null /dev/null <(ls -d "$(pwd -P)/"*); fi'
# or
alias ls2='if [[ $(diff <(ls "$PWD" | sed "s|.*|$(ls -d "$PWD/")&|g") <(ls -d "$(pwd -P)/"*) | wc -l) == "0" ]]; then ls -l; else paste -d " -> " <(ls "$PWD") /dev/null /dev/null /dev/null <(ls -d "$(pwd -P)/"*); fi'