如何使用命名管道作为临时文件?

用户名

我使用的一个vim插件使用此脚本将一些输入传递给不支持从stdin读取的linter。

set -eu

# All of the following arguments are read as command to run.
file_extension="$1"
shift

temp_dir=$(mktemp -d 2>/dev/null || mktemp -d -t 'ale_linter')
temp_file="$temp_dir/file$file_extension"
trap 'rm -r "$temp_dir"' EXIT

while read -r; do
  echo "$REPLY" >> "$temp_file"
done

"$@" "$temp_file"

起初,我对他们为什么不使用这样的东西感到有些困惑

some input | some_program /dev/stdin

但是在尝试ghc了linter之后,我发现它抱怨/ dev / stdin表示不是真实文件(不是)

所以我想知道我可以使用namedpipe代替临时文件吗?我对写入临时文件不满意的原因是SSD的运行状况,如果有更好的方法可以这样做,为什么不这样做呢?

斯蒂芬·查泽拉斯(Stephane Chazelas)

不,那拒绝这些文件的程序通常拒绝他们,理由是该文件不是可查找(他们需要倒带等后,在任意的偏移量,或多次访问内容)。或者他们想多次打开文件。他们可能还想重写(部分)文件或截断文件。

在任何情况下,未命名pipe(如和|和一样/dev/stdin)或命名都没有区别。

实际上,在Linux上,/dev/stdin当stdin是管道(命名或不命名)的行为与命名管道完全相同时,程序将无法将其/dev/stdin与真正的命名管道区分开

在其他系统上,它并不完全相同,但是实际上,打开/dev/stdin或命名管道将为您提供管道的文件描述符,无论哪种方式都无法找到。

因此,您需要创建临时文件。请注意,有些外壳使其更容易使用。使用zsh,只是:

#! /bin/zsh -
"$@" =(cat)

在Linux上并且使用在此处的文档中使用已删除的临时文件的外壳程序(例如bashzsh以及的某些实现ksh),您可以执行以下操作:

#! /bin/bash -
"$@" /dev/fd/3 3<< EOF
$(cat)
EOF

但是,如果文件包含NUL字符或以空行结尾,则可能会破坏文件的内容。

请注意,从版本5开始,bash会将此处doc临时文件设为只读,因此,如果应用程序需要对该文件进行修改,则可以使用以下命令恢复写权限:

#! /bin/bash -
{
  chmod u+w /dev/fd/3 && # only needed in bash 5+
    "$@" /dev/fd/3
} 3<< EOF
$(cat)
EOF

while read自您提出要求以来,有关该循环的注意事项

首先read -r没有变量名是无效的sh语法。sh语法被指定POSIX(ISO 9945,也IEEE标准1003.1)之类的C语法由ISO 9899指定。

该规范中,您会注意到这read需要一个变量名参数。省略时的行为是不确定的,并且实际上随sh解释器实现的不同而不同

bash是GNUsh解释器,就像gccGNU C编译器一样。双方bashgcc有超过什么这些标准指定的扩展。

在的情况下readbash对待read -r好像它是IFS= read -r REPLY在POSIX规范中,IFS= read -r REPLY读取stdin直到到达一个\n字符或输入的末尾,然后将读取的字符存储到$REPLY变量中,如果读取了换行符(全行),则返回成功退出状态,否则返回失败(如EOF)如果读取的数据包含NUL字符或不构成有效字符的字节序列,则行为未定义。

在的情况下bash,即使它们不构成有效字符,它也会存储读取的字节,并删除NUL字符。

read -r就像是read -r REPLYkshzsh在报告错误yashash为基础的POSIX样弹。

echo未指定的行为,除非其参数不包含反斜杠字符,并且第一个不包含反斜杠字符-n

因此,总而言之,除非您知道sh要处理的特定实现(和版本),否则您将无法确定要执行的操作

while read -r; do
  echo "$REPLY" >> "$temp_file"
done

会做。bash特定情况下,仅当数据不包含NUL字符,以换行符结尾并且没有一行与^-[neE]+$扩展的正则表达式匹配(和/或取决于环境或如何bash编译像sh操作系统/ X,不包含反斜杠字符)。

这也是非常低效的,而不是您在shell中处理文本的方式

在这里,您想要:

cat > "$temp_file"

cat是一个标准命令,当不提供任何参数时,它将按原样将其stdin转储到其stdout

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章