外壳 - 带有重音的解压缩文件夹



我在Windows中使用此结构创建了一个" .zip":

myfile.zip
    - trénsfèst
        - file1.png
        - file2.png
        - file3.png

使用PHP,我发送shell_exec在我的服务器上放置myfile.zip。在我的shell文件中,我需要解压缩此文件以将结构在特定文件夹中获取。当我执行unzip myfile.zip时,所有口音都没有解释:

Archive:  myfile.zip
creating: tr?n'sf?rt/
inflating: tr?n'sf?rt/file1.png
inflating: tr?n'sf?rt/file2.png
inflating: tr?n'sf?rt/file3.png

当我尝试删除文件夹时,有一些正方形可以更换重音。是否有解决方案可以用所有口音解开我的文件夹

谢谢

Windows通常根据语言环境编码文件名。例如,对于俄罗斯设置,它通常在CP866中编码文件名。将文件名放入同一语言环境中的拉链中,即根据创建档案的系统的位置。

检测编码

我几年前试图解决这个问题,我得出结论,总的来说,没有办法可靠地检测编码。在PHP中,您可以尝试使用ZipArchivemb_detect_encoding

$zip = new ZipArchive;
$filename = $argv[1];
if (! $zip->open($filename))
  die("failed to open $filenamen");
for ($i = 0; $i < $zip->numFiles; ++$i) {
  $encoding = mb_detect_encoding($zip->getNameIndex($i), 'auto');
  if (! $encoding) {
    trigger_error("Failed to detect encoding for " . $zip->getNameIndex($i), E_USER_ERROR);
    exit(1);
  }
  $zip->renameIndex($i, iconv($encoding, 'UTF-8', $zip->getNameIndex($i)));
}
$zip->extractTo('/home/ruslan/tmp/unzippped/');
$zip->close();

,但根据我的经验,mb_detect_encoding不是很准确。

您可以尝试使用enca工具来检测编码如下:

ls -1 folder | enca -L ru

其中ru是语言代码(所有语言代码均可通过enca --list languages获得)。但这需要您猜测该语言。要实际将文件名从一个编码转换为UTF-8,您可以使用enconv,例如:

ls -1 folder | enconv -L russian -x UTF-8

,但是,您再次需要猜测语言。

因此,我建议尝试使用上面的一种方法检测编码,并要求用户从所有可用编码的列表中选择编码。默认情况下可以在列表中选择自动检测的编码。就个人而言,我选择让用户无需智能自动检测即可选择编码。

当您知道源编码

UNZIP用-p选项支持管道流。但它仅适用于批量数据。也就是说,它不会将所有未压缩内容传递给程序的文件中分开:

unzip -p foo |更多=>通过管道将foo.zip的内容发送到程序中更多

解析原始流显然是一项艰巨的任务。一种方法是将文件提取到目录中,然后用这样的脚本转换文件名:

$path = $argv[1];
$from_encoding = isset($argv[2]) ? $argv[2] : 'CP866';
if ($handle = opendir($path)) {
  while ($file = readdir($handle)) {
    rename($file, iconv($from_encoding, 'UTF-8', $file));
  }
  closedir($handle);
}

示例用法:

php script.php directory Windows-1252

另外,使用ZipArchive如下。

$zip = new ZipArchive;
$filename = $argv[1];
$from_encoding = isset($argv[2]) ? $argv[2] : 'CP866';
$zip->open($filename) or die "failed to open $filenamen";
for ($i = 0; $i < $zip->numFiles; ++$i) {
  $zip->renameIndex($i, iconv($from_encoding,'UTF-8', $zip->getNameIndex($i)));
}
$zip->extractTo('/target/directory/');
$zip->close();

示例用法:

php script.php file.zip Windows-1252

感谢Ruslan Osmanov,但我找到了一个解决方案。解压缩我的zip文件后,我使用convmv,所以这是我的过程:

unzip myfile.zip
convmv --notest -r -f WINDOWS-1252 -t utf8

感谢这篇文章:Windows-1252 to UTF-8编码

最新更新