Shell - 解压带重音的文件夹
Shell - Unzip folder with accent
我在 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 编码文件名。文件名以相同的区域设置放入 Zip,即区域设置取决于创建存档的系统。
检测编码
我tried to solve this problem some years ago, and I came to conclusion that in general there is no way to detect encoding reliably. In PHP you can try with ZipArchive
and mb_detect_encoding
:
$zip = new ZipArchive;
$filename = $argv[1];
if (! $zip->open($filename))
die("failed to open $filename\n");
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 | more => send contents of foo.zip via pipe into program more
解析原始流显然是一项艰巨的任务。一种方法是将文件提取到目录中,然后使用如下脚本转换文件名:
$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 $filename\n";
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
感谢这个 post : Windows-1252 to UTF-8 encoding
我在 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 编码文件名。文件名以相同的区域设置放入 Zip,即区域设置取决于创建存档的系统。
检测编码
我tried to solve this problem some years ago, and I came to conclusion that in general there is no way to detect encoding reliably. In PHP you can try with ZipArchive
and mb_detect_encoding
:
$zip = new ZipArchive;
$filename = $argv[1];
if (! $zip->open($filename))
die("failed to open $filename\n");
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 | more => send contents of foo.zip via pipe into program more
解析原始流显然是一项艰巨的任务。一种方法是将文件提取到目录中,然后使用如下脚本转换文件名:
$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 $filename\n";
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
感谢这个 post : Windows-1252 to UTF-8 encoding