【问题标题】:Why can't I work with files in ".." from within a symbolic link?为什么我不能从符号链接中处理“..”中的文件?
【发布时间】:2013-02-18 12:05:48
【问题描述】:

我的目录结构如下:

misha@misha-lmd:~/tmp$ ls -l
total 4.0K
-rw-r--r-- 1 misha lmd 21 Feb 18 21:00 hello.py
lrwxrwxrwx 1 misha lmd 20 Feb 18 21:01 symlink -> /home/misha/nobackup/

接下来,我尝试以下操作:

misha@misha-lmd:~/tmp$ cd symlink
misha@misha-lmd:~/tmp/symlink$ cat ../hello.py 
cat: ../hello.py: No such file or directory

为什么这不起作用?

如果我这样做:

misha@misha-lmd:~/tmp/symlink$ cd ..
misha@misha-lmd:~/tmp$ cat hello.py
print "Hello World!"

那么一切都很好。 cd 处理 .. 正确,但 cat 没有。这是什么魔法,我如何让事情按照我想要的方式运作?

编辑

好的,多亏了这里的一些答案,我对正在发生的事情有了更多的了解。首先,cd 实际上不是可执行文件,它是 shell 的内置命令(在本例中为 bash):

misha@misha-lmd:~/tmp$ type cd
cd is a shell builtin

如果您man bash,您可以找到关于 bash 用于其内部管理的所有环境变量,包括在目录中移动。还有其他内置函数,例如 pwd,它们的对应项实际上是可执行文件:

misha@misha-lmd:~/tmp/symlink$ type pwd
pwd is a shell builtin
misha@misha-lmd:~/tmp/symlink$ /bin/pwd
/home/misha/nobackup
misha@misha-lmd:~/tmp/symlink$ /bin/pwd -L
/home/misha/tmp/symlink

/bin/pwd 可执行文件默认打印物理路径,但也可以打印给定 `-L' 开关的逻辑路径。同样,当我尝试这样做时:

misha@misha-lmd:~/tmp/symlink$ cat ../hello.py 
cat: ../hello.py: No such file or directory

事情失败了,因为.. 被解释为物理父目录,而不是逻辑目录。这让我可以细化我的问题

当我为可执行文件指定命令行参数时,如何让.. 表示逻辑父级,而不是物理父级?

【问题讨论】:

  • 什么是/home/misha/nobackup/?它是现有目录吗?

标签: linux bash command-line


【解决方案1】:

因为符号链接目录中的目录.. 是您的主目录。

../something 表示“转到.. 目录”,而不是“剥离最后一个路径组件”。

您可以尝试pwd -P 来查看您在更改为符号链接后的位置。

【讨论】:

  • 如果在符号链接目录中,.. 是 ~,为什么“cd ..”带我回到 ~/tmp 而不是 ~? cd 是在做一些 cat 做不到的聪明事情吗?
  • 是的,bash 做了“一些聪明的事情”。试试man bash 并寻找cd/^ +cd 应该可以带你到那里)。
【解决方案2】:

它不起作用,因为没有/home/misha/hello.py。符号链接不会创建新目录,而是指向链接的目录。所以当你 cd 到一个符号链接时,你实际上是 cd 到那个目录,

您是否期望 shell 会记住您来自符号链接的位置?好吧,不是那样工作的:)

【讨论】:

  • 嗯...好吧,shell确实记得,正如您在提示符中很容易看到的那样;-)
  • 这个问题是由cd 命令实际上像那样工作 引起的(除非它是cd -P),而不是系统调用中的.. 路径名解释。跨度>
【解决方案3】:

试试

cat $(cd ..; pwd)/hello.pycat

不知道对你有没有帮助。

编辑:
如果你真的需要它,这里有一个方法(但它有点难看):

$ lcat ( ) ( cd "${1%/*}"; cat "${1##*/}"; )
# use it like 'cat'
$ lcat ../hello.py

对函数体使用( ... ) 而不是{ ... } 使其在子shell 而不是当前shell 中执行cd
当我尝试它时,它也适用于“文件名完成”。
但这只是解决cat,我认为用于其他命令也可能更复杂。

$ lcmd ( ) ( local cmd="$1"; shift; cd "${1%/*}"; $cmd "${1##*/}"; )

然后做例如lcmd cat ../hello.py

【讨论】:

  • 谢谢。虽然这样可行,但它确实很冗长,并且会破坏自动完成功能。
猜你喜欢
  • 1970-01-01
  • 2022-01-15
  • 1970-01-01
  • 1970-01-01
  • 2012-08-22
  • 2020-09-23
  • 1970-01-01
  • 2012-10-03
  • 1970-01-01
相关资源
最近更新 更多