制作一个临时目录,用于解压缩zip文件

时间:2009-11-10 13:01:41

标签: php file zip tempdir

我有一个脚本可以检查包含许多匹配的PDF +文本文件的zipfile。我想解压缩,或者以某种方式从zipfile中读取文本文件,然后从文本文件中挑选一些信息,看看文件版本是否正确。

我正在查看tempnam()函数以找到制作临时文件的等效函数,但也许有人可以更好地解决问题。

indexfile看起来像这样。 (->用于TAB char)。 我已经完成了从文本文件中提取版本的功能,并检查它是否已经正确,只有解包,tmpdir或其他一些我正在寻找的解决方案。

1000->filename->file version->program version->customer no->company no->distribution
2000->pagenumber->more info->more info->...

6 个答案:

答案 0 :(得分:29)

非常简单(部分来自PHP手册):

<?php

function tempdir() {
    $tempfile=tempnam(sys_get_temp_dir(),'');
    // you might want to reconsider this line when using this snippet.
    // it "could" clash with an existing directory and this line will
    // try to delete the existing one. Handle with caution.
    if (file_exists($tempfile)) { unlink($tempfile); }
    mkdir($tempfile);
    if (is_dir($tempfile)) { return $tempfile; }
}

/*example*/

echo tempdir();
// returns: /tmp/8e9MLi

请参阅:http://de.php.net/manual/en/function.tempnam.php

请查看以下Wi​​ll的解决方案。

=&GT;我的答案不应该是接受的答案了。

答案 1 :(得分:11)

如果使用mktemp在Linux上运行并访问exec函数,则另一个选项如下:

<?php

function tempdir($dir=NULL,$prefix=NULL) {
  $template = "{$prefix}XXXXXX";
  if (($dir) && (is_dir($dir))) { $tmpdir = "--tmpdir=$dir"; }
  else { $tmpdir = '--tmpdir=' . sys_get_temp_dir(); }
  return exec("mktemp -d $tmpdir $template");
}

/*example*/

$dir = tempdir();
echo "$dir\n";
rmdir($dir);

$dir = tempdir('/tmp/foo', 'bar');
echo "$dir\n";
rmdir($dir);

// returns:
//   /tmp/BN4Wcd
//   /tmp/foo/baruLWFsN (if /tmp/foo exists, /tmp/baruLWFsN otherwise)

?>

这避免了上面的潜在(虽然不太可能)种族问题,并且具有与tempnam功能相同的行为。

答案 2 :(得分:4)

我想对@Mario Mueller的回答添加一个改进,因为他受到可能的竞争条件的影响,但我认为以下不应该是:

function tempdir(int $mode = 0700): string {
    do { $tmp = sys_get_temp_dir() . '/' . mt_rand(); }
    while (!@mkdir($tmp, $mode));
    return $tmp;
}

这是有效的,因为如果mkdir已经存在,false会返回$tmp,导致循环重复并尝试其他名称。

另请注意,我已添加了对$mode的处理,默认情况下确保只有当前用户才能访问该目录,因为mkdir的默认值为{{ 1}}否则。

强烈建议您使用关闭功能以确保在不再需要时删除目录,即使您的脚本以意外方式退出*。为方便起见,我使用的完整功能会自动执行此操作,除非0777参数设置为$auto_delete

false

这意味着默认情况下,// Deletes a non-empty directory function destroydir(string $dir): bool { if (!is_dir($dir)) { return false; } $files = array_diff(scandir($dir), ['.', '..']); foreach ($files as $file) { if (is_dir("$dir/$file")) { destroydir("$dir/$file"); } else { unlink("$dir/$file"); } } return rmdir($dir); } function tempdir(int $mode = 0700, bool $auto_delete = true): string { do { $tmp = sys_get_temp_dir() . '/' . mt_rand(); } while (!@mkdir($tmp, $mode)); if ($auto_delete) { register_shutdown_function(function() use ($tmp) { destroydir($tmp); }); } return $tmp; } 创建的任何临时目录都具有tempdir()的权限,并在脚本结束时自动删除(及其内容)。

注意:*如果脚本被终止可能不是这种情况,为此您可能需要考虑注册信号处理程序。

答案 3 :(得分:1)

这个问题有很多矫枉过正的答案。一个简单的答案是:

@ECHO off
SETLOCAL
SETLOCAL EnableDelayedExpansion

REM path to ffmpeg
SET ffmpeg=C:\path\to\ffmpeg\bin
REM source movies from
SET movieSource=C:\path\to\your\mp4\movies
REM tmp dir
SET tmpDir=C:\path\for\tmp\files\and\final\output


REM setup positon, color, background, font for the text overlays
REM filterComplex, quotes have to be escaped! -> \"
REM BITC - Burned In Time Code
SET filterComplexTimecode=drawtext=fontfile='C\:\\Windows\\Fonts\\arial.ttf': timecode='10\:00\:00\:00': timecode_rate=24: x=(w-tw)/2: y=h-(1*lh)-3: fontsize=20: fontcolor=white@0.4: box=1: boxcolor=0x00000000@0.4: boxborderw=4
REM Date
SET filterComplexDate=drawtext=fontfile='C\:\\Windows\\Fonts\\arial.ttf': text='%%{localtime\: %%d.%%m.%%Y %%H\\\:%%M}': x=(w-tw-3): y=h-(1*lh)-3: fontsize=20: fontcolor=white@0.4: box=1: boxcolor=0x00000000@0.4: boxborderw=4
REM Shotname
SET filterComplexShotname=drawtext=fontfile='C\:\\Windows\\Fonts\\arial.ttf': x=0: y=h-(1*lh)+1: fontsize=20: fontcolor=white@0.4: box=1: boxcolor=0x00000000@0.4: boxborderw=4:



REM create a list of all files
FOR /F "tokens=*" %%F IN ('dir %movieSource%\*.mp4 /b  ^| sort') DO ECHO file '%movieSource%\%%F' >> %tmpDir%\filelist.txt

REM gather more informations for each file
ECHO ; filename, durationInSeconds > %tmpDir%\fileNameDuration.txt

FOR /R %movieSource%\ %%F IN (*.mp4) DO (
  REM Reset current duration to 0 (zero) for each loop
  SET curDuration=0

  REM get the filename without file extenion
  SET fileName=%%~nF

  REM get the duration of a single clip
  REM and write it to a tmp textfile
  %ffmpeg%\ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 %%~fF > %tmpDir%\fileTempDuration.txt
  REM read the textfile again into a variable
  SET /p curDuration=<%tmpDir%\fileTempDuration.txt

  REM write the filename and the duration to a new list of all files
  ECHO !fileName!,!curDuration! >> %tmpDir%\fileNameDuration.txt
)

REM concate a filter complex string for ffmpeg with all clipnames as textlayer with a inpoint and outpoint
SET filterComplexShotnameCombined=
REM floating numbers are not supported by batch, so we need to work-around that
CALL :IntAsFP b=0.000000
FOR /F "eol=; tokens=1,2* delims=," %%i IN (%tmpDir%\fileNameDuration.txt) DO (
  CALL :IntAsFP a=%%j
  CALL :IntToFP inPoint=!b! 6
  SET /A c=a+b
  SET /A b=c
  CALL :IntToFP outPoint=!c! 6
  REM just to check whats going on...
  ECHO name: %%i   duration: %%j   inPoint: !inPoint!   outPoint: !outPoint!
  SET filterComplexShotnameCombined=!filterComplexShotnameCombined!, !filterComplexShotname! text=%%i: enable=between(t\,!inPoint!\,!outPoint!^^^)
)

REM bringing all together. filter complex for current date, one for the normal timecode, and the actual shotnames.
SET filterComplexCombined=-filter_complex "%filterComplexDate%, %filterComplexTimecode% %filterComplexShotnameCombined%"

REM just to check...
ECHO %filterComplexCombined%
%ffmpeg%\ffmpeg.exe %async% -f concat -i %tmpDir%\filelist.txt %filterComplexCombined% %fps% %codec% %loglevel% %tmpDir%\output.mov


:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

REM Integer to FloatingPoint

:IntAsFP Int=FP
set FP=%2
set %1=%FP:.=%
exit /B


:IntToFP FP=Int digits
set Int=%2
set %1=!Int:~0,-%3!.!Int:~-%3!
exit /B
  1. 获取临时文件名。
  2. 创建目录(在temp文件后附加一个后缀,以避免文件名冲突。)
  3. 完成。

答案 4 :(得分:0)

另一种可能性是使用临时文件作为一种信号量来保证目录名的唯一性。然后,创建一个名称基于文件名的目录。

define ('TMP_DIR', '/tmp'); // sys_get_temp_dir() PHP 5 >= 5.2.1
define ('TMP_DIR_PREFIX', 'tmpdir_');
define ('TMP_DIR_SUFFIX', '.d');

/* ************************************************************************** */

function createTmpDir() {
  $tmpFile = tempnam(TMP_DIR, TMP_DIR_PREFIX);
  $tmpDir = $tmpFile.TMP_DIR_SUFFIX;
  mkdir($tmpDir);
  return $tmpDir;
}

function rmTmpDir($tmpDir) {
  $offsetSuffix = -1 * strlen(TMP_DIR_SUFFIX);
  assert(strcmp(substr($tmpDir, $offsetSuffix), TMP_DIR_SUFFIX) === 0);
  $tmpFile = substr($tmpDir, 0, $offsetSuffix);

  // Removes non-empty directory
  $command = "rm -rf $tmpDir/";
  exec($command);
  // rmdir($tmpDir);

  unlink($tmpFile);
}

/* ************************************************************************** */

答案 5 :(得分:0)

图我将证明简单的答案。只需为您的应用程序特定字符串设置前缀

$tmpDir = sprintf('%s%sPREFIX-%s', sys_get_temp_dir(), DIRECTORY_SEPARATOR, mt_rand());

mkdir($tmpDir);