Shell - 将可变内容写入文件

use*_*083 77 linux bash shell

我想将变量(此处称为var)的内容复制到文件中.

文件名存储在另一个变量中destfile.

我这样做有问题.这是我尝试过的:

cp $var $destfile
Run Code Online (Sandbox Code Playgroud)

我也用dd命令尝试了同样的事情......显然shell认为$var是指一个目录,所以告诉我找不到目录.

我该如何解决这个问题?

pb2*_*b2q 117

使用echo命令:

var="text to append";
destdir=/some/directory/path/filename

if [ -f "$destdir" ]
then 
    echo "$var" > "$destdir"
fi
Run Code Online (Sandbox Code Playgroud)

代表文件的if测试$destdir.

>附加截断文件之后的文本.如果您只想将文本附加$var到文件现有内容中,请>>改为使用:

echo "$var" >> "$destdir"
Run Code Online (Sandbox Code Playgroud)

cp命令用于复制文件(到文件),而不是用于将文本写入文件.

  • 如果`$ var`是`-e text to append`,并且实际上不写`-e`,则会失败 (5认同)
  • `echo`还为变量添加了一个尾随换行符. (3认同)
  • 需要更多的引号-现在,将变量值内的任何空白运行都转换为单个空格,将扩展glob表达式,等等。 (2认同)
  • 另一件事 - 你需要在结束引号和`"$ destdir"中的`]`之间留一个空格. (2认同)
  • 因为 `echo $var` 依赖于 shell 来扩展你的变量,它对空白和特殊字符之类的东西不起作用。您可以改用`perl -e 'print($ENV{var})'`,它将精确输出变量的值。 (2认同)

Tre*_*awa 24

echo有问题,如果var包含类似的东西-e,它将被解释为一个标志.另一种选择是printf,但printf "$var" > "$destdir"会扩展变量中的任何转义字符,因此如果变量包含反斜杠,则文件内容将不匹配.但是,因为printf只在格式字符串中将反斜杠解释为转义,所以可以使用%s格式说明符将确切的变量内容存储到目标文件中:

printf "%s" "$var" > "$destdir"

  • 基本上是可移植性(和可靠性)问题。https://unix.stackexchange.com/a/65819 …或者对于我们中间的致命者:“printf”更好,继续。 (3认同)
  • 如果变量字符串中有换行符,例如来自三重引号或heredoc, printf 也很好。echo 不能很好地处理换行符。 (2认同)
  • 如果你,朝圣者同伴,阅读这个答案并考虑删除“$var”周围的双引号 - 停止它。在某些情况下,如果没有引号或单引号,它将无法工作。只需接受必须使用双引号即可。这些知识花费了我大约一天的时间来调试一个损坏的 GitHub Actions 工作流程,其中我将私钥(带有换行符)从秘密保存到文件中...... (2认同)

Eri*_*ric 18

如果您的变量,上述答案都不起作用:

  • 以..开始 -e
  • 以..开始 -n
  • 以..开始 -E
  • 包含一个\后跟一个n
  • 不应该在其后附加额外的换行符

所以他们不能依赖任意字符串内容.

在bash中,您可以使用"here strings"作为:

cat <<< "$var" > "$destdir"
Run Code Online (Sandbox Code Playgroud)

  • 据我所知,cat总是会在文件的末尾插入一个换行符,无论变量末尾没有换行符(尽管在大多数情况下这可能是件好事).[回答使用printf](/sf/answers/3459288451/)似乎避免插入尾随换行符. (5认同)

qwe*_*rtz 9

如果我理解你正确,你想复制$var一个文件(如果它是一个字符串).

echo $var > $destdir
Run Code Online (Sandbox Code Playgroud)

  • 如果你没有将`$ var`括在引号中,那么在某些情况下,文件的内容与$ var的内容不是100%相等.例如,当"回显"包含RSA密钥的变量时,您将在文件中获得无效密钥. (4认同)
  • 如果$ var包含空格或-e则失败 (3认同)

Chr*_*jer 6

上述所有工作,但还必须解决一个不需要首先出现的问题(转义和特殊字符):当变量被 shell 扩展时的特殊字符。首先不要这样做(变量扩展)。直接使用变量,无需扩展。

此外,如果您的变量包含一个秘密并且您想将该秘密复制到一个文件中,您可能不希望在命令行中进行扩展,因为 shell 命令的跟踪/命令回显可能会泄露该秘密。意味着,$var在命令行中使用的所有答案都可能通过将变量内容暴露给 shell 的跟踪和日志记录而具有潜在的安全风险。

用这个:

printenv var >file
Run Code Online (Sandbox Code Playgroud)

这意味着,对于 OP 问题:

printenv var >"$destfile"
Run Code Online (Sandbox Code Playgroud)

注意:变量名区分大小写。

  • 这应该是公认的答案。它正确回答了OP的问题,没有潜在的危险副作用。它唯一的缺点是它不是内置的 shell,尽管几乎每个 Linux 机器上都可以找到它。我只是想指出它区分大小写。`printenv user` 不打印任何内容,而 `printenv USER` 打印当前用户名(至少在我的计算机上)。 (4认同)
  • 这应该是公认的答案。它也适用于“太聪明而不顾自己的利益”的逃避例程,就像詹金斯那样。 (2认同)
  • 这仅适用于环境变量,不适用于本地脚本的变量。您必须“导出”这些变量,如果您的值包含任何秘密,则意味着以相同用户身份运行的任何进程都将能够从进程表中读取这些值,并且所有子进程也将继承这些值,可能会将信息泄露给您未预料到的其他进程。这不是一个理想的情况。使用 `printf "$var"` 或 `foo &lt;&lt;&lt; "$var"` 应该在所有情况下都有效。 (2认同)