【问题标题】:How to create a temporary directory?如何创建临时目录?
【发布时间】:2011-01-08 02:28:39
【问题描述】:

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

temp=`tempfile`
rm -f $temp
  # <breakpoint>
mkdir $temp

问题是,当它运行到时,恰好有另一个程序想做同样的事情,它mkdir-ed了一个临时目录同名,会导致本程序失败。

【问题讨论】:

    标签: bash temporary-directory


    【解决方案1】:

    使用mktemp -d。它创建一个具有随机名称的临时目录,并确保该文件不存在。使用后记得删除目录。

    【讨论】:

    • 我不得不使用mktemp -d -t &lt;prefix&gt;
    • 这是 OS X 与 Linux 的对比。有关适用于两者的版本,请参阅此问题:unix.stackexchange.com/questions/30091/…
    • 另外,请参阅 Ortwin 下面的答案,因为这可以确保清理工作也完成。
    • 为什么说“你需要记住在使用后删除目录。”?这不是有点违背使用临时目录的目的吗?
    • @M.K.Safi 我认为主要目的是创建一个空目录,您可以在其中存储临时文件,而不会弄乱文件系统的其他部分。您可以选择是否/何时删除它。如果它在 /tmp 中创建它,那么它应该在系统重新启动时被清除。
    【解决方案2】:

    为了获得更强大的解决方案,我使用如下内容。这样脚本退出后临时目录将始终被删除。

    清理函数在EXIT 信号上执行。这保证了清理函数总是被调用,即使脚本在某处中止。

    #!/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
    ...
    

    来自here 的 bash 脚本目录。

    重击traps

    【讨论】:

    • FreeBSD 注意! FreeBSD 上的 mktemp 没有 -p 选项,cleanuprm -rf 你的当前目录!跨度>
    • 好点,更新了脚本以检查是否可以创建临时目录。
    • @madfriend 真的吗?如果 mktemp 失败,WORK_DIR 将为空,这意味着命令将只是 rm -rf 没有参数。我不使用 FreeBSD,但如果 rm -rf 等同于 rm -rf .,我会感到非常惊讶
    • @jbg 是的,我现在也觉得很奇怪——这应该不是什么大问题。我可能已经调整了这个脚本的旧版本,以便相对于当前目录计算临时目录的路径,从而导致 人类灭绝 当前目录被删除。
    • 为了使它更好,您可以避免空目录或至少使用以下解决方案将问题包含在目录中:1.TMPWORKDIR=$(basename 'mktemp -d -p /tmp/git/'),然后 2.rmdir /tmp/git/"${TMPWORKDIR}"。如果变量现在为空,您仍然会退回到/tmp/git/ 而不是整个系统。在答案中考虑这样的事情,我很乐意同意。 ;)
    【解决方案3】:

    我最喜欢的单线是

    cd $(mktemp -d)
    

    【讨论】:

    • rm $(pwd)? :P
    • 也很有用:pushd $(mktemp -d) ... popd
    • @ArranCudbard-Bell 应该是 rm -r $(pwd)
    • @piggybox 坦率地说,我会非常谨慎使用rm -r $(pwd)。考虑临时目录创建因任何原因失败的可能性(可能 /tmp 文件系统已满或由于错误已重新以只读方式挂载?);然后cd $(mktemp -d) 将评估为cd,这将更改为用户的主目录,随后将被删除。
    • if pushd $(mktemp -d || echo BADMPDIR); then ........ ; rm -r $(pwd); popd; fi 可能是安全的
    【解决方案4】:

    下面的 sn -p 将安全地创建并清理一个临时目录。

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

    #!/bin/bash
    
    # set -x # un-comment to see what's going on when you run the script
    
    # Create a temporary directory and store its name in a variable.
    TEMPD=$(mktemp -d)
    
    # Exit if the temp directory wasn't created successfully.
    if [ ! -e "$TEMPD" ]; then
        >&2 echo "Failed to create temp directory"
        exit 1
    fi
    
    # Make sure the temp directory gets removed on script exit.
    trap "exit 1"           HUP INT PIPE QUIT TERM
    trap 'rm -rf "$TEMPD"'  EXIT
    

    【讨论】:

    • 虽然这是一个有趣的错误处理解决方案,但对优点和可能的缺点进行更多解释会很好。
    • 1.) -d 检查目录。 2.) 终止已经是这些信号的默认设置。
    • 这里不要建议 TMPDIR 作为变量名,因为这通常是系统的临时目录。 en.wikipedia.org/wiki/TMPDIR
    • 谢谢@spawn,我重命名了 TMPDIR 变量。
    【解决方案5】:

    这里是关于如何使用模板创建临时目录的简单说明。

    1. 安全地创建一个临时文件或目录,并打印其名称。
    2. TEMPLATE 在最后一个组件中必须至少包含 3 个连续的“X”。
    3. 如果没有指定 TEMPLATE,它将使用 tmp.XXXXXXXXXX
    4. 创建的目录是 u+rwx,减去 umask 限制。
    
    PARENT_DIR=./temp_dirs # (optional) specify a dir for your tempdirs
    mkdir $PARENT_DIR
    
    TEMPLATE_PREFIX='tmp' # prefix of your new tempdir template
    TEMPLATE_RANDOM='XXXX' # Increase the Xs for more random characters
    TEMPLATE=${PARENT_DIR}/${TEMPLATE_PREFIX}.${TEMPLATE_RANDOM}
    
    # create the tempdir using your custom $TEMPLATE, which may include
    # a path such as a parent dir, and assign the new path to a var
    NEW_TEMP_DIR_PATH=$(mktemp -d $TEMPLATE)
    echo $NEW_TEMP_DIR_PATH
    
    # create the tempdir in parent dir, using default template
    # 'tmp.XXXXXXXXXX' and assign the new path to a var
    NEW_TEMP_DIR_PATH=$(mktemp -p $PARENT_DIR)
    echo $NEW_TEMP_DIR_PATH
    
    # create a tempdir in your systems default tmp path e.g. /tmp 
    # using the default template 'tmp.XXXXXXXXXX' and assign path to var
    NEW_TEMP_DIR_PATH=$(mktemp -d)
    echo $NEW_TEMP_DIR_PATH
    
    # Do whatever you want with your generated temp dir and var holding its path
    
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-09-21
      • 2013-09-18
      • 2010-10-11
      • 2017-10-06
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多