我正在尝试让 GNU 找到直到指定文件名的排除条目。
以此树为例:
./foo
./foo/another.txt
./foo/bar
./foo/bar/world
./foo/bar/world/test.txt
./foo/bar/world/hello.txt
(和其他目录中还会有一堆其他文件world
,这就是为什么我不只是搜索hello.txt
)。
我想要匹配除“test.txt”及其父目录之外的所有内容。
输出应该只是foo/bar/world/hello.txt
。
此命令产生了正确的结果,但它非常混乱,并且如果存在多个同名目录,则会产生错误的结果:
find * ! -name test.txt -a ! -name foo -a ! -name bar -a ! -name world
答案1
告诉find
你你只对文件感兴趣,而不是目录。
find ./foo -type f ! -name test.txt
更新:
假设我们有这个稍微复杂一点的例子:
$ find ./foo
./foo
./foo/baz
./foo/baz/b.csv
./foo/baz/a.txt
./foo/bar
./foo/bar/c.txt
./foo/bar/world
./foo/bar/world/hello.txt
./foo/bar/world/test.txt
如果您的目标是删除某些内容,则需要指定-depth
文件在其目录之前显示:
$ find ./foo -depth
./foo/baz/b.csv
./foo/baz/a.txt
./foo/baz
./foo/bar/c.txt
./foo/bar/world/hello.txt
./foo/bar/world/test.txt
./foo/bar/world
./foo/bar
./foo
如果您知道要保留的路径,我们可以设计一个与其部分匹配的正则表达式:
$ find ./foo -depth -regextype posix-extended -regex '^\./foo(/bar(/world(/test.txt)?)?)?'
./foo/bar/world/test.txt
./foo/bar/world
./foo/bar
./foo
然后我们可以否定正则表达式来获得想要删除的内容:
$ find ./foo -depth -regextype posix-extended ! -regex '^\./foo(/bar(/world(/test.txt)?)?)?'
./foo/baz/b.csv
./foo/baz/a.txt
./foo/baz
./foo/bar/c.txt
./foo/bar/world/hello.txt
答案2
如果您知道树的确切深度(即您想要从第三个文件夹开始获取文件),您可以使用:
find . -mindepth $depth ! -name test.txt
通过您的目录结构,我得到:
$ find . -mindepth 4 ! -name test.txt
./foo/bar/world/hello.txt
这正是您所期望的。
编辑:这应该更好(但更丑!)。它找到所在test.txt
的目录并找到其中的所有文件。优点是它完全独立于父路径,它会自动计算它们。
EXCLUDEFNAME="test.txt"; find $(find . -name "$EXCLUDEFNAME" -exec dirname {} \; -quit) -mindepth 1 ! -name "$EXCLUDEFNAME"
多行更好:
EXCLUDEFNAME="test.txt"
targetpath="$(find . -name "$EXCLUDEFNAME" -exec dirname {} \;)"
find "$targetpath" -mindepth 1 ! -name "$EXCLUDEFNAME"