如何创建一个临时目录?


229

我用来创建tempfile,删除它,并将其重新创建为目录:

tmpnam=`tempfile`
rm -f $tmpnam
mkdir "$tmpnam"

问题是,如果另一个进程X在一个进程之后rm -f X和之前意外执行tempfile,则另一个进程可能具有相同的名称mkdir X

Answers:


341

使用mktemp -d。它使用随机名称创建一个临时目录,并确保该文件尚不存在。不过,您需要记住在使用目录后将其删除。


25
我不得不使用mktemp -d -t <prefix>
Heath Borders

17
这是OS X vs Linux。请参阅此问题以获取适用于两个版本的版本: unix.stackexchange.com/questions/30091/…– jwhitlock 2014
6

2
另外,请参阅以下Ortwin的答案,因为这样可以确保也进行清理。
Mathiasdm '16

5
为什么说“尽管使用目录,但您需要记住删除目录。”?这样做是否违反了使用临时目录的目的?
MK Safi

73

对于更强大的解决方案,我使用类似以下的内容。这样,脚本退出后,临时目录将始终被删除。

EXIT信号执行清除功能。这样可以确保始终调用cleanup函数,即使脚本在某处中止。

#!/bin/bash    

# the directory of the script
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"

# the temp directory used, within $DIR
# omit the -p parameter to create a temporal directory in the default location
WORK_DIR=`mktemp -d -p "$DIR"`

# check if tmp dir was created
if [[ ! "$WORK_DIR" || ! -d "$WORK_DIR" ]]; then
  echo "Could not create temp dir"
  exit 1
fi

# deletes the temp directory
function cleanup {      
  rm -rf "$WORK_DIR"
  echo "Deleted temp working directory $WORK_DIR"
}

# register the cleanup function to be called on the EXIT signal
trap cleanup EXIT

# implementation of script starts here
...

bash脚本的目录从这里开始

打击陷阱


26
FreeBSD警告!FreeBSD上的mktemp没有-p选项,cleanup它将rm -rf您的当前目录!
疯狂的朋友,2017年

1
好了,更新了脚本以检查是否可以创建临时目录。
Ortwin Angermeier

1
@madfriend真的吗?如果mktemp失败,WORK_DIR将为空,这意味着该命令将不rm -rf带任何参数。我不使用FreeBSD,但如果rm -rf相当于rm -rf .
jbg

@jbg是的,现在对我来说也很奇怪-这不应该是一个很大的问题。我可能已经对该脚本的旧版本进行了调整,以便相对于当前目录计算出临时目录的路径,从而导致<s>人类灭绝</ s>当前目录的删除。
疯狂的朋友'17

1
为了使其更好,您可以使用以下解决方案来避免目录为空或至少将问题包含在目录中:1. TMPWORKDIR=$(basename 'mktemp -d -p /tmp/git/')然后2 rmdir /tmp/git/"${TMPWORKDIR}".。如果该变量现在为空,则您仍将/tmp/git/不使用整个系统。考虑一下答案中的类似内容,我会很乐意同意的。;)
Beco博士

64

我最喜欢的单线是

cd $(mktemp -d)

10
rm $(pwd)?:P
Arran Cudbard-Bell 2014年

19
也有用:pushd $(mktemp -d)...popd
Ponkadoodle

4
@ ArranCudbard-Bell应该是rm -r $(pwd)
储钱罐

31
@piggybox坦白说,我会非常谨慎地使用rm -r $(pwd)。考虑由于某种原因临时目录创建失败的可能性(可能是/ tmp文件系统已满或由于错误而已被挂载为只读?);然后cd $(mktemp -d)将评估对cd用户主目录的更改,然后将其删除。
儒勒(Jules)

1
可能会很安全if pushd $(mktemp -d || echo BADMPDIR); then ........ ; rm -r $(pwd); popd; fi
AndreyS Scherbakov '18

9

以下代码段将安全地创建一个临时目录(-d),并将其名称存储到TMPDIR。(TMPDIR稍后在代码中显示了变量的示例用法,该变量用于存储可能会被修改的原始文件。)

当收到任何指定信号时,第一trap行执行exit 1命令。第二行删除(清理)程序的退出(正常和异常)。在检查是否成功避免了在未知状态下意外执行退出陷阱之后,我们将初始化这些陷阱。trap$TMPDIRmkdir -d$TMPDIR

#!/bin/bash

# Create a temporary directory and store its name in a variable ...
TMPDIR=$(mktemp -d)

# Bail out if the temp directory wasn't created successfully.
if [ ! -e $TMPDIR ]; then
    >&2 echo "Failed to create temp directory"
    exit 1
fi

# Make sure it gets removed even if the script exits abnormally.
trap "exit 1"           HUP INT PIPE QUIT TERM
trap 'rm -rf "$TMPDIR"' EXIT

# Example use of TMPDIR:
for f in *.csv; do
    cp "$f" "$TMPDIR"
    # remove duplicate lines but keep order
    perl -ne 'print if ++$k{$_}==1' "$TMPDIR/$f" > "$f"
done

1
尽管这对于错误处理是一个有趣的解决方案,但是对优点和可能的缺点进行更多的解释会更好。
墨菲

1.)-d检查目录。2.)终止已经是那些信号的默认设置。
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.