我一直在研究具有多种功能的脚本。
我正在尝试添加一个函数,显示“/usr/share/applications”文件夹中所有应用程序的 Whatis 命令的输出,而不显示“没有合适的内容”的行。
我当前的命令尝试是:
whatis $(ls /usr/share/applications | cut -d "." -f 1) | grep -i -v "nothing appropriate"
我遇到的问题是 grep 命令似乎不起作用,因此包含短语“没有合适的”的行仍然显示。
我还尝试了多种替代方法,包括使用“replace”和“sed”命令将不需要的行转换为空白,但这些也未能解决问题。
所有上述尝试,我都尝试过直接输出命令,并且还尝试将输出路由到文件中,并对文件的“cat”输出执行过滤器。
有人可以推荐其他选择吗?
答案1
错误消息通常写入到stderr
,而您仅通过管道传输stdout
到grep
。要通过管道传输 stdout 和 stderr,在类似 Bourne 的 shell 中fish
,您可以执行以下操作:
whatis... 2>&1 | grep -v 'nothing appropriate'
请注意,这意味着 stdout 和 stderr 最终会在 stdout 上合并。
那里的 shell 看到一个管道,因此它将它分成whatis... 2>&1
和 ,grep -v 'nothing appropriate'
并用左侧管道的 stdout(文件描述符 1)作为管道的写入端,右侧管道的 stdin(fd 0)作为另一个管道来检测它们该管道的末端,每一端在单独的进程中同时运行。
在每一侧,都会处理重定向。2>&1
说:将 fd 2 重定向到与 fd 1 上打开的相同的内容,这里是管道。所以 fd 1 和 2 都进入管道。
类似 rc 的 shell 的等效语法是whatis... >[2=1] | grep...
and with csh
-like shells:(whatis... |& grep...
也适用于 zsh)。
使用ksh93
、zsh
或bash
,您还可以stderr
仅发送到过滤管道:
whatis... 2> >(grep -v 'nothing appropriate' >&2)
但请注意,grep
不会等待该命令,因此您可能会在命令返回后看到其他错误消息。这可以通过以下方式避免zsh
:
{whatis...} 2> >(grep -v 'nothing appropriate' >&2)
(或者更痛苦的ksh93
是bash
)。
在 中yash
,您可以使用进程重定向(语法类似流程替代,但不同之处在于它是一个重定向运算符,而不是扩展),同样的问题是不等待过滤命令:
whatis... 2>(grep -v 'nothing appropriate' >&2)
请注意,cut -d "." -f 1
您最终会更改org.gnome.Settings.desktop
为org
而不是org.gnome.Settings
.由于您正在调用 split+glob,因此对于包含$IFS
或 glob 字符的应用程序名称也会出现问题。
有了zsh
,你会这样做:
whatis -- /usr/share/applications/*.desktop(:t:r) |& grep -v 'nothing appropriate'
其中:t
采用t
文件的 ail (dirname) 和:r
根名称(不带扩展名)并且|&
是2>&1 |
.
在 中bash
,您可以执行以下操作:
(
shopt -s failglob
set /usr/share/applications/*.desktop
set -- "${@##*/}"
whatis -- "${@%.*}" 2>&1
) | grep -v 'nothing appropriate'
哪里"${@##*/}"
相当于:t
,"${@%.*}"
相当于:r
.
使用 GNU ls
9.0 或更高版本,您还可以执行以下操作:
ls --zero /usr/share/applications/ |
LC_ALL=C sed -zn 's/\.desktop$//p' |
xargs -r0 whatis -- 2>&1 |
grep -v 'nothing appropriate'
其中ls --zero
以可后处理的格式输出列表,sed
删除.desktop
扩展名并在存在替换时输出结果(因此排除没有.desktop
扩展名的文件),xargs
将列表传递给whatis
,并grep
过滤掉nothing appropriate
错误。
使用 GNU basename
,您还可以执行以下操作:
(
shopt -s failglob
basename -zs .desktop /usr/share/applications/*.desktop
) |
xargs -r0 whatis -- 2>&1 |
grep -v 'nothing appropriate'
另请注意,桌面文件的名称通常与它们执行的可执行文件的名称(如果有)不匹配,因此可能没有相应的手册页。
whatis
您还可以提取这些.desktop
文件的一些字段,而不是将根名称传递给。例如:
(cd /usr/share/applications &&
grep -HPom1 -e '^GenericName=\K.*' -- *.desktop
)
GenericName
将提取这些文件中第一次出现的字段的值。