如何使用“查找”转到该文件的目录


11

我想找到一个文件,然后输入包含它的目录。我尝试过,find /media/storage -name "Fedora" | xargs cd但是我当然会is not a directory出错。

如何使用单行命令进入其父目录?


1
如果有来自多个位置的多个文件怎么办?
Sergiy Kolodyazhnyy

@Serg Im正在搜索Fedora * .iso文件,我知道只有一个。我想,如果还有更多,它将进入第一个难题
Hrvoje T

在bash with中shopt -s globstar,您可以使用cd /media/storage/**/Fedora,但这并不会在第一次匹配时就停止评估glob(因此,它比steeldriver的解决方案要慢。对于交互式使用,我通常要做的是触摸鼠标并复制/粘贴目录名称, (和Alt + Backspace键根据需要去掉结尾的路径组件我不想),但如果你这样做了很多我想一个shell函数可能是值得做的。
彼得·科德斯

1
顺便说一句,xargs cd不可能工作。 cd只能作为shell内置程序使用,因为它必须修改shell本身的上下文。有没有办法一个xargs子进程可以做到这一点。IDK(如果这就是您的意思),或者find打印的路径包含空格,这些空格由xargs分割,因为您没有使用它-d \n或任何东西。或者find -exec {} \;
彼得·科德斯

注意:您不能那样跑cdcd是内置的bash,如果cd是单独的命令,则它将更改(自己的)dir,然后退出(将您返回外壳,即与以前处于相同状态,不更改dir)。
ctrl-alt-delor

Answers:


14

至少如果您有GNU find,可以-printf '%h'用来获取目录

       %h     Leading directories of file's name (all but the last ele‐
              ment).  If the file name contains no slashes (since it is
              in  the  current  directory)  the %h specifier expands to
              ".".

所以你可能会做

cd "$(find /media/storage -name "Fedora" -printf '%h' -quit)"

-quit多个cd文件匹配的情况下,应当防止使用多个参数。


1
-quit也不一定受支持。在NetBSD中称为-exit,请参见unix.stackexchange.com/a/62883/117599
phk

2
如果没有printf,您可以改用-exec dirname吗?
Guy

@Guy好主意,是的,听起来也应该起作用
Steeldriver

6

类似于steeldriver的解决方案,但结合使用-execdir(如果您find支持的话,例如GNU或FreeBSD findpwd

cd "$(find /media/storage -name "Fedora" -execdir pwd \; -quit)"

-quit如果仅存在一个结果,并且对整个目录进行爬网没有问题,则是可选的。在NetBSD上-exit,在OpenBSD上不存在。


那是\;为了什么?
Hrvoje T

1
@HrvojeT就像-exec它告诉find命令执行的参数结束一样。但是由于我们想在pwd这里不带参数调用,因此我们将其放在\;右边。
phk

有没有find支持execdir的实现-printf %h?对我来说似乎不太可能。不幸的是POSIX都不需要:/
Peter Cordes

1
@PeterCordes FreeBSD findfreebsd.org/cgi/man.cgi? find%281%29 (刚刚在FreeBSD 11安装上确认了这一点。)
phk

@PeterCordes与NetBSD(netbsd.gw.com/cgi-bin/man-cgi?find++NetBSD-current)和OpenBSD(man.openbsd.org/OpenBSD-current/man1/find.1)相同。后者完全不支持-quit/ -exit
phk

5

您可以使find在找到的目录中运行新的Shell。

exec find /media/storage -name "Fedora" -execdir "$SHELL" \;

,之后当前目录将是其中包含名为Fedora的文件的目录。;)

显然,如果您以交互方式键入命令,这只会做您想要的事情。


4

zsh

cd /media/storage/**/Fedora([1]:h)

cd到包含一个名为第一(排名不分先后)目录Fedora

  • **:任何级别的目录(默认情况下会省略隐藏的目录,请使用Dglob限定符将其包括在内)
  • [1]:仅第一个
  • :hhead修饰符:取目录名。

与此相反cd "$(find ...)",如果目录名称以换行符结尾,则也可以使用。另一个好处是,当没有匹配的目录时,您会收到一条不匹配错误消息(而在大多数shell中,它cd ""会默默地执行任何操作)。

缺点是它将/media/storage在返回之前对整个对象进行爬网。


在bash中,cd具有多个arg始终仅查看第一个arg,因此cd $(dirname /media/storage/**/Fedora)shopt -s globstar如果路径中没有空格,则可以(使用)工作。为了正确引用它,我认为bash数组是最简单的:target=(/media/storage/**/Fedora); cd "${target%/*}"。但是到那时,使用鼠标复制/粘贴查找输出而不是交互式地提供输出会更快。
彼得·科德斯

2
@PeterCordes,许多dirname实现不会接受多个参数。请注意,它不是空格,而是当前使用的任何字符$IFS(默认情况下为空格,制表符和换行符)和通配符。请注意,bashs 是否cd会接受多个参数取决于它的编译方式(CD_COMPLAINSin config-top.h)。可以想象,将来的版本bash还将最终像zsh中一样实现两个arg功能。
斯特凡Chazelas

谢谢。我只是看了GNU coreutils dirname手册页。dirname版本仍然很糟糕。我只提到了它,您可以交互式尝试以防它起作用。我的基于数组的版本没有任何这些问题,因为"${target%*/}"它仅扩展到第一个数组元素(带/Fedora剥离的)。我认为该版本对路径名中的所有可能字符均具有足够的鲁棒性。
彼得·科德斯
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.