diff -r eb3cb6495f22 Lib/tarfile.py --- a/Lib/tarfile.py Tue Jan 21 21:13:25 2014 -0500 +++ b/Lib/tarfile.py Wed Jan 22 12:39:33 2014 +0800 @@ -1844,6 +1844,8 @@ """ self._check() + import locale + stdout_encoding = locale.getpreferredencoding() for tarinfo in self: if verbose: print(stat.filemode(tarinfo.mode), end=' ') @@ -1857,13 +1859,29 @@ print("%d-%02d-%02d %02d:%02d:%02d" \ % time.localtime(tarinfo.mtime)[:6], end=' ') - print(tarinfo.name + ("/" if tarinfo.isdir() else ""), end=' ') + tarinfo_dir = b"/" if tarinfo.isdir() else b"" + try: + print(tarinfo.name + str(tarinfo_dir), end=' ') + except UnicodeEncodeError: + print(tarinfo.name.encode(stdout_encoding, errors='replace') + + tarinfo_dir, end=' ') if verbose: - if tarinfo.issym(): - print("->", tarinfo.linkname, end=' ') - if tarinfo.islnk(): - print("link to", tarinfo.linkname, end=' ') + try: + if tarinfo.issym(): + print("->", tarinfo.linkname, end=' ') + if tarinfo.islnk(): + print("link to", tarinfo.linkname, end=' ') + except UnicodeEncodeError: + if tarinfo.issym(): + print(b"->", tarinfo.linkname.encode(stdout_encoding, + errors='replace'), + end=' ') + if tarinfo.islnk(): + print(b"link_to", + tarinfo.linkname.encode(stdout_encoding, + errors='replace'), + end=' ') print() def add(self, name, arcname=None, recursive=True, exclude=None, *, filter=None): diff -r eb3cb6495f22 Lib/test/test_tarfile.py --- a/Lib/test/test_tarfile.py Tue Jan 21 21:13:25 2014 -0500 +++ b/Lib/test/test_tarfile.py Wed Jan 22 12:39:33 2014 +0800 @@ -1824,6 +1824,16 @@ out = self.tarfilecmd(opt, tmpname) self.assertEqual(out, expected) + def test_list_print_unencodable_characters(self): + for tar_name in testtarnames: + for opt in '-l', '--list': + out = self.tarfilecmd(opt, tar_name) + self.assertIn(b'ustar/umlauts-???????', out) + self.assertIn(b'misc/regtype-hpux-signed-chksum-???????', out) + self.assertIn(b'misc/regtype-old-v7-signed-chksum-???????', out) + self.assertIn(b'pax/bad-pax-???', out) + self.assertIn(b'pax/hdrcharset-???', out) + def test_list_command_verbose(self): self.make_simple_tarfile(tmpname) with support.captured_stdout() as t: