Answers:
tmpfile=$(mktemp /tmp/abc-script.XXXXXX)
: ...
rm "$tmpfile"
通过打开文件描述符并将其删除,可以确保在脚本退出(包括杀死和崩溃)时删除文件。/proc/$PID/fd/$FD
只要打开文件描述符,文件就保持可用(对于脚本;不是真的对其他进程有效,但是可以解决)。当它关闭(内核在进程退出时自动执行)时,文件系统删除该文件。
tmpfile=$(mktemp /tmp/abc-script.XXXXXX)
exec 3>"$tmpfile"
rm "$tmpfile"
: ...
echo foo >&3
/proc
-除了没有它的系统。
exec 3> "$tmpfile"
办?仅当tmpfile是独立脚本时,这才有用吗?
cat <&3
会给Bad file descriptor
。如果您修复或删除它,我将不胜感激。错误信息并没有太大帮助。
使用mktemp
创建一个临时文件或目录:
temp_file=$(mktemp)
或直接使用:
temp_dir=$(mktemp -d)
在脚本末尾,您必须删除临时文件/目录:
rm ${temp_file}
rm -R ${temp_dir}
mktemp /tmp
在--tmpdir
参数指定的目录或目录中创建文件。
trap "rm -f $temp_file" 0 2 3 15
在创建文件后立即使用,以便在脚本退出或停止运行时ctrl-C
仍将其删除。
EXIT
唯一的钩子会发生什么trap
?
kill -9 $somepid
。那个特殊的杀手信号是致命的,什么也没有发生。
bash -c 'echo $$; trap "echo foo" 0; sleep 5'
EXIT
就足够了。
如果您使用的系统具有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"
EXIT
唯一的钩子会发生什么trap
?
tmpfile
仍然可以在脚本退出之前删除,但是在脚本收到其他信号时不会删除。
That's not what happens
?
mktemp
源于HP / UX,具有不同的语法。Todd C. Miller在90年代中期为OpenBSD创建了另一种版本(由FreeBSD和NetBSD复制),后来又以独立实用程序的形式提供(www.mktemp.org)。那是在Linux上通常使用的,直到2007年将一个(几乎兼容的)mktemp
实用程序添加到GNU coreutils 为止。说的不是一个真正mktemp
的GNU实用程序。
一些外壳程序具有内置功能。
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
命令完成后,该文件将自动删除。
在这里,文件或点击这里,字符串bash
和zsh
实现为删除临时文件。
因此,如果您这样做:
exec 3<<< test
文件描述符3连接到包含的已删除临时文件test\n
。
您可以通过以下方式获取其内容:
cat <&3
如果在Linux上,您还可以通过以下方式对该文件进行读写 /dev/fd/3
$ exec 3<<< test
$ cat <&3
test
$ echo foo > /dev/fd/3
$ cat /dev/fd/3
foo
(其他一些shell使用管道,或者/dev/null
如果here文档为空,则可以使用)。
没有mktemp
POSIX实用程序。但是,POSIX指定了mkstemp(template)
C API,并且m4
标准实用程序使用mkstemp()
相同名称的m4函数公开该API 。
mkstemp()
为您提供了一个文件名,该文件名具有随机部分,可以保证在调用函数时该部分不存在。它确实以无竞争的方式创建了权限为0600的文件。
因此,您可以执行以下操作:
tmpfile=$(
echo 'mkstemp(template)' |
m4 -D template="${TMPDIR:-/tmp}/baseXXXXXX"
) || exit
但是请注意,您需要在退出时进行清理,尽管如果您只需要读写固定次数的文件,则可以像创建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
您可以打开文件以读取一次,然后在两次读取之间进行倒带,但是没有POSIX实用程序可以进行倒带(lseek()
),因此您无法在POSIX脚本中进行可移植的操作(zsh
(sysseek
内置)和ksh93
(<#((...))
运算符)尽管这样做)。
<()
=(...)
。
在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
我通常使用临时文件的工作流程是因为我正在测试某些bash脚本。我想要完成tee
它,以便可以看到它正在工作,并将输出保存到我的过程的下一个迭代中。我创建了一个名为tmp
#!/bin/bash
echo $(mktemp /tmp/$(date +"%Y-%m-%d_%T_XXXXXX"))
这样我就可以像
$ some_command --with --lots --of --stuff | tee $(tmp)
我喜欢将日期时间格式化为随机值之前的原因是,它使我能够轻松找到刚创建的tmp文件,并且不必考虑下次要命名的内容(而只需要获取我的dang脚本即可)上班)。