我目前正在使用grep
和解决一个问题ls
。目标是列出当前目录中作为链接文件的所有行。我的目录中有 3 个链接文件,但是当我执行命令时它只显示一个。
这是我正在输入的内容:
ls -lR | grep l*
任何帮助,将不胜感激。谢谢
答案1
@NasirRiley 走在正确的轨道上。要列出当前目录中的符号链接,请运行find . -mindepth 1 -maxdepth 1 -type l
.测试:
$ cd "$(mktemp --directory)"
$ mkdir foo
$ touch foo/bar baz
$ ln --symbolic foo/bar ban
$ ln --symbolic bar foo/bat # symlink in subdirectory, should be ignored
$ find . -mindepth 1 -maxdepth 1 -type l
./ban
答案2
您的管道存在一些问题。
解析输出
ls
这不是一个好主意(也可以看看为什么*不*解析`ls`(以及该怎么做)?)。它的格式没有标准化,文件名可以包含除 NUL 和/
.因此,它不保证以明确的形式列出文件名。经常给出的示例涉及换行符(请注意ls
以不同方式调用可能会导致不同的、可能不明确的结果):$ touch 'foo > bar' $ ls -1 'foo'$'\n''bar' $ ls | cat foo bar
foo
和 是bar
两个不同的文件或同一文件名的两个部分吗?递归搜索目录中给定类型文件的安全方法是
find
。未转义的字符串
l*
被 shell 解释为通配表达。它扩展为文件名列表(通过广泛的“文件”的定义l
) 从当前目录开始。# In a directory you created for testing purposes $ rm *; touch foo; ln -s foo link1; ln -s foo link2; ln -s foo link3 $ set -x; ls -lR | grep l* + ls -lR + grep link1 link2 link3
shell
xtrace
选项(即set -x
,在多个 shell 中可用并由POSIX) 对于显示文件名扩展(通配)的效果很有用:l*
扩展为link1 link2 link3
并因此在 的内容中grep
搜索字符串(通过符号链接和)。 (link1
foo
link2
link3
grep
当在要搜索的模式之后给出文件名列表时,不读取标准输入)。如果你恰好有一名称以以下字符开头的文件
l
:# In a directory you created for testing purposes $ rm *; touch foo; ln -s foo link1; ln -s foo Link2; ln -s foo Link3 $ set -x; ls -lR | grep l* + ls -lR + grep link1 lrwxrwxrwx 1 user group 3 May 1 03:04 link1 -> foo
然后在
grep
其标准输入( 的输出ls
)中搜索字符串link1
,此处匹配一行。 (读取标准输入是grep
在没有给出文件名或文件名参数为 时执行的操作-
)。你应该引用文字字符串作为参数传递,以防止 shell 执行文件名扩展。作为替代方案,在 shell 支持的情况下,可以使用
set -f
.如果当前目录中没有文件名以 开头,则通配表达式保持不变并作为第一个位置参数
l
传递。然后将其解释为正则表达式(默认为grep
grep
BRE变种)其内容为“对于任何输入行,匹配一个选修的l
(任何地方)”,有效匹配任何内容:# In a directory you created for testing purposes $ rm *; touch foo $ ls -lR .: total 0 -rw-r--r-- 1 user group 0 May 1 02:49 foo $ set -x; ls -lR | grep l* + ls -lR + grep 'l*' .: total 0 -rw-r--r-- 1 user group 0 May 1 03:14 foo
要匹配以文字开头的字符串,
l
您需要一个锚定表达式:grep '^l'
。
答案3
正如您所知,您正在寻找的命令是:
ls -l | grep '^l'
不一定需要引号。
删除-R
on 选项ls
是因为您指定需要当前目录,而不是目录树。
无论哪种方式,指向您的答案find
可能是更好的解决方案。