Bhu*_*esh 243 shell-script tmp
在运行脚本时,我想在/tmp目录中创建一个临时文件。
执行该脚本后,该脚本将清除该脚本。
如何在shell脚本中做到这一点?
Hau*_*ing 302
tmpfile=$(mktemp /tmp/abc-script.XXXXXX)
: ...
rm "$tmpfile"
Run Code Online (Sandbox Code Playgroud)
您可以通过打开文件的文件描述符并将其删除来确保在脚本退出(包括终止和崩溃)时删除文件。/proc/$PID/fd/$FD只要文件描述符处于打开状态,该文件就保持可用(对于脚本;不是真正用于其他进程,而是一种变通方法)。当它关闭时(当进程退出时内核会自动执行),文件系统会删除该文件。
# create temporary file
tmpfile=$(mktemp /tmp/abc-script.XXXXXX)
# create file descriptor 3 for writing to a temporary file so that
# echo ... >&3 writes to that file
exec 3>"$tmpfile"
# create file descriptor 4 for reading from the same file so that
# the file seek positions for reading and writing can be different
exec 4<"$tmpfile"
# delete temp file; the directory entry is deleted at once; the reference counter
# of the inode is decremented only after the file descriptor has been closed.
# The file content blocks are deallocated (this is the real deletion) when the
# reference counter drops to zero.
rm "$tmpfile"
# your script continues
: ...
# example of writing to file descriptor
echo foo >&3
# your script continues
: ...
# reading from that file descriptor
head -n 1 <&4
# close the file descriptor (done automatically when script exits)
exec 3>-
Run Code Online (Sandbox Code Playgroud)
cha*_*aos 106
使用mktemp创建一个临时文件
temp_file=$(mktemp)
Run Code Online (Sandbox Code Playgroud)
或者,创建一个临时目录:
temp_dir=$(mktemp -d)
Run Code Online (Sandbox Code Playgroud)
在脚本结束时,您必须删除临时文件或目录
rm ${temp_file}
rm -R ${temp_dir}
Run Code Online (Sandbox Code Playgroud)
mktemp在/tmp目录或--tmpdir参数给定的目录中创建文件。
Sté*_*las 25
某些外壳具有内置功能。
zsh的=(...)过程替代形式是使用一个临时文件。例如,=(echo test)扩展为包含test\n.
$ {cat $file; ls -l /dev/fd/3; echo test2 >&3; cat $file} 3<> ${file::==(echo test)}
test
lrwx------ 1 stephane stephane 64 Jan 30 11:19 /dev/fd/3 -> /tmp/zshMLbER0
test2
Run Code Online (Sandbox Code Playgroud)
命令完成后,该文件将自动删除。
bash5.1 之前版本中的here-documents 或 here-strings并zsh作为已删除的临时文件实现(就像在 70 年代后期引入 here-documents 的 Bourne shell 中的情况一样)。
所以如果你这样做:
exec 3<<< test
Run Code Online (Sandbox Code Playgroud)
文件描述符 3 连接到一个已删除的临时文件,其中包含test\n.
您可以通过以下方式获取其内容:
cat <&3
Run Code Online (Sandbox Code Playgroud)
如果在 Linux 上,您也可以通过 读取或写入该文件/dev/fd/3,但使用 bash 5.0 版,您首先需要恢复对其的写入权限(bash 在该版本中明确删除了该权限):
$ exec 3<<< test
$ cat <&3
test
$ chmod u+w /dev/fd/3 # only needed in bash 5.0
$ echo foo > /dev/fd/3
$ cat /dev/fd/3
foo
Run Code Online (Sandbox Code Playgroud)
(其他一些 shell 使用管道,或者/dev/null如果此处的文档为空,则可能会使用)。
没有mktempPOSIX 实用程序。然而,POSIX 指定了一个mkstemp(template)C API,m4标准实用程序使用mkstemp()同名的m4 函数公开该 API 。
mkstemp()为您提供一个带有随机部分的文件名,该部分保证在调用函数时不存在。它确实以无竞争的方式创建了具有 0600 权限的文件。
所以,你可以这样做:
tmpfile=$(
echo 'mkstemp(template)' |
m4 -D template="${TMPDIR:-/tmp}/baseXXXXXX"
) || exit
Run Code Online (Sandbox Code Playgroud)
但是请注意,您需要在退出时处理清理工作,但如果您只需要写入和读取文件固定次数,您可以在为 here-doc/here- 创建之后打开并删除它上面的字符串方法:
tmpfile=$(
echo 'mkstemp(template)' |
m4 -D template="${TMPDIR:-/tmp}/baseXXXXXX"
) || exit
# open once for writing, twice for reading:
exec 3> "$tempfile" 4< "$tempfile" 5< "$tempfile"
rm -f -- "$tmpfile"
cmd >&3 # store something in the temp file
exec 3>&- # fd no longer needed
# read the content twice:
cat <&4
cat <&5
Run Code Online (Sandbox Code Playgroud)
您可以打开文件进行一次读取,然后在两次读取之间倒带,但是没有 POSIX 实用程序可以执行倒带 ( lseek()),因此您不能在 POSIX 脚本 ( zsh(sysseek内置) 和ksh93(<#((...))运算符) 中可移植地执行此操作做吧)。
cuo*_*glm 18
如果您在具有mktemp 的系统上,您应该将其用作其他答案。
使用 POSIX 工具箱:
umask 0177
tmpfile=/tmp/"$0"."$$"."$(awk 'BEGIN {srand();printf "%d\n", rand() * 10^10}')"
trap 'rm -f -- "$tmpfile"' INT TERM HUP EXIT
: > "$tmpfile"
Run Code Online (Sandbox Code Playgroud)
Swa*_*anS 13
以下是 Hauke Laging 的一些改进答案:
#!/bin/bash
tmpfile=$(mktemp) # Create a temporal file in the default temporal folder of the system
# Lets do some magic for the tmpfile to be removed when this script ends, even if it crashes
exec {FD_W}>"$tmpfile" # Create file descriptor for writing, using first number available
exec {FD_R}<"$tmpfile" # Create file descriptor for reading, using first number available
rm "$tmpfile" # Delete the file, but file descriptors keep available for this script
# Now it is possible to work with the temporal file
echo foo >&$FD_W
echo bar >&$FD_W # Note that file descriptor always concatenates, not overwrites
cat <&$FD_R
Run Code Online (Sandbox Code Playgroud)