是否有命令可以在没有重定向、管道或函数的情况下将文本写入文件?

Pad*_*dau 16 shell-script quoting yad

管道和重定向是 Linux 中两个最强大的功能,我喜欢它们。

但是,我遇到了一种情况,我需要在不使用管道、重定向或函数的情况下将一段固定的文本写入文件。

我正在使用 Bash 以防万一。

第一:为什么?

如果有更简单的解决方案,我会解释原因。

我有一个带有一些菜单条目的后台 yad 通知。在某些菜单项中,我希望通知将一段固定的文本写入文件。这是我的意思的一个例子。

yad --notification --command=quit --menu='Example!echo sample >text.txt'
Run Code Online (Sandbox Code Playgroud)

问题是 yad 不接受重定向,所以它从字面上打印字符串sample >text.txt而不是重定向。

同样,管道符号 ( |) 是 yad 中的分隔符;但是如果你改变它,yad 会把它当作一个文字字符。例如:

yad --notification --command=quit --separator='#' --menu='Example!echo sample | tee text.txt'
Run Code Online (Sandbox Code Playgroud)

这从字面上打印字符串sample | tee text.txt而不是管道。

编写一个供 yad 调用的函数也没有意义,因为 yad 运行在它自己的空间中并且无法识别该函数。

因此我的问题

因此,我想要一个像echo,cat或者printf将输出文件作为参数而不是重定向的命令。我已经搜索过这样的命令,但找不到。

当然,我可以自己编写并将其放在默认路径中:

FILENAME="${1}"
shift
printf '%s\n' "${*}" >"${FILENAME}"
Run Code Online (Sandbox Code Playgroud)

进而

yad --notification --command=quit --menu='Example!myscript text.txt sample'
Run Code Online (Sandbox Code Playgroud)

但是,如果 Linux 还没有这样的东西,我确实会感到惊讶!

谢谢

Gil*_*il' 32

这有点像XY 问题,但幸运的是,您已经解释了真正的问题,因此可以给出有意义的答案。

当然,有些命令可以将文本写入文件,而无需依赖其环境来打开文件。例如,sh可以这样做:将参数-cecho text >filename.

请注意,这确实满足此处“无需重定向”的要求,因为 的输出sh不会重定向到任何地方。sh运行的程序内部有一个重定向,但没关系,这只是sh工作原理的内部细节。

但这能解决您的实际问题吗?您的实际问题是从 yad 操作将文本写入文件。为了解决这个问题,您需要确定 yad 操作是什么。不幸的是,手册没有记录这一点。它所说的只是

menu:STRING

设置通知图标的弹出菜单。STRING必须在形式name1[!action1[!icon1]]|name2[!action2[!icon2]]...。空名称将分隔符添加到菜单。值的分隔符(例如|)与--separator参数集。菜单项的分隔符(例如!)用--item-separator参数设置。

操作是一个字符串,但 Unix 命令是一个字符串列表:命令名称及其参数。有几种可行的方法可以将字符串转换为命令名称及其参数,包括:

  • 将字符串视为命令名称并在不带参数的情况下调用它。由于echo fooprints foo,而不是尝试执行程序echo foo,这不是 yad 所做的。
  • 将字符串传递给 shell。由于echo >filenameprints >filename,而不是filenamewrite to ,这不是 yad 所做的。
  • 一些自定义字符串拆分。在这一点上,这大概是 yad 所做的,但具体取决于它是如何做到的,您的问题的解决方案可能会有所不同。

查看源代码,将popup_menu_item_activate_cb调用 Glib 函数的操作传递给它g_spawn_command_line_async。此函数使用g_shell_parse_argvwhich 具有以下行为拆分给定的字符串,这几乎从来不是可取的,但可以解决:

将命令行解析为参数向量,与 shell 的方式大致相同,但没有 shell 将执行的许多扩展(不支持变量扩展、globs、运算符、文件名扩展等)。结果被定义为与您从 UNIX98 /bin/sh 获得的结果相同,只要输入不包含任何不受支持的 shell 扩展。如果输入确实包含这样的扩展,它们将按字面传递。

因此,您可以通过使用前缀sh -c '和结尾来运行 shell 命令'。如果您需要在 shell 命令中使用单引号,请编写'\''. 或者,您可以通过以 为前缀、以sh -c "结尾""$\`在命令中出现的任何字符之前添加反斜杠来运行 shell命令。请注意嵌套引用,因为操作本身在调用 yad 的 shell 脚本中被引用。

yad --notification \
  --menu='Simple example!sh -c "echo sample text >text.txt"' \
  --menu='Single-double-single quotes!sh -c "echo '\''Here you can put everything except single quotes literally: two  spaces, a $dollar and a single'\''\'\'''\''quote.'\'' >text.txt"' \
  --menu="Double-single-double quotes!sh -c 'echo \"Here punctuation is a bit tricky: two  spaces, a \\\$dollar and a single'\\''quote.\"' >text.txt'"
Run Code Online (Sandbox Code Playgroud)

  • 当一个程序的文档如此糟糕时,你必须从字面上*阅读源代码*来弄清楚如何使用它...... (12认同)
  • @MathematicalOrchid 它被称为 [*Use the Source, Luke*](https://www.urbandictionary.com/define.php?term=Use%20the%20Source%2C%20Luke)。 (6认同)
  • @MathematicalOrchid:阅读源代码仍然比无法访问源代码要好。 (2认同)

Ipo*_*cer 5

如果你想使用 shell 的特性,那么运行一个 shell:

yad --notification --command=quit --menu='Example!sh -c "echo sample >text.txt"'
Run Code Online (Sandbox Code Playgroud)