你能在 shell 使用临时文件之前清理它们吗?

你能在 shell 使用临时文件之前清理它们吗?

如果我的程序崩溃,我想避免出现临时文件。

UNIX 的奇妙之处在于您可以使文件保持打开状态 - 即使在删除它之后也是如此。

因此,如果您打开该文件,请立即将其删除,然后然后进行缓慢的处理,即使程序崩溃,用户也很有可能不必清理文件。

在 shell 中我经常看到类似的东西:

generate-the-file -o the-file
[...loads of other stuff that may use stdout or not...]
do_slow_processing < the-file
rm the-file

但如果程序崩溃之前rm用户就必须进行清理the-file

在 Perl 中你可以这样做:

open(my $filehandle, "<", "the-file") || die;
unlink("the-file");
while(<$filehandle>) {
  # Do slow processing stuff here
  print;
}
close $filehandle;

然后文件一打开就会被删除。

shell中有类似的构造吗?

答案1

这在 csh、tcsh、sh、ksh、zsh、bash、ash、sash 中进行了测试:

echo foo > the-file
(rm the-file; cat) < the-file | do_slow_processing
do_other_stuff

或者如果您愿意:

(rm the-file; do_slow_processing) < the-file
do_other_stuff

有趣的是,它也适用于 fifo:

mkfifo the-fifo
(rm the-fifo; cat) < the-fifo | do_slow_processing &
echo foo > the-fifo

这是因为在写入内容之前,读者会被阻塞。

答案2

generate-the-file > the-file
exec 5< the-file
rm the-file
...
do_slow_processing 0<&5

笔记:

  • 您需要在没有可执行文件的情况下运行 exec,因此它会影响 shell 本身的描述符
  • 最多仅提供 9 个 fd
  • 如果需要文件名,可以使用 /proc/self/fd/X 。此接口不可在 UNIX 风格之间移植(不过它可能适合您)。
  • 尝试再次读取 fd(例如两次调用cat 0<&5)将会失败,因为您处于 EOF 位置。您需要倒带它,或者通过阅读来克服它/proc/self/fd/X
  • 在上面的大多数情况下,您可以在没有实际文件的情况下进行操作,但可以执行一个简单的操作generate-the-file | do_slow_processing

更新:

OP 提到generate-the-file可能不会在标准输出中产生输出。对此有一些习语:

  • 指定输出文件-.通常接受输出文件名 - 表示 stdout。这是经 POSIX.1-2017 认可:

    准则 13: 对于使用操作数来表示要打开以进行读取或写入的文件的实用程序,“-”操作数应仅用于表示标准输入(或标准输出,当从上下文中清楚地知道正在指定输出文件时)或文件名为-.

(对于那些明确定义的实用程序之外的实用程序,它是实现定义的,但很有可能您的generate-the-file工具支持它)

这不适用于所有 shell,并且需要操作系统支持 fd 文件名。

答案3

bashshell 中,处理清理的方法是使用trap内置的 EXIT(在bashshell 中键入help trap):

trap 'rm temp-file' EXIT

此功能也存在于dashshell 中,sh在现代 Linux 发行版中经常被称为别名。

相关内容