Convert a Windows-created ZIP to Linux (internal paths issue)












4















I have a .zip created on a Windows machine (outside of my control). The zip file contains paths that I need to preserve when I unzip.



However, when I unzip, all files end up like:
unzip_dir/windowpathseparatormyfile.ext



I've tried both, with and without -j option.
My issue is that I need that path information under windowpathseparator. I need that file structure to be created when I unzip.



I can mv the file and flip the to / easily enough in a script, but then there are errors that the destination path directories do not exist. My workaround for now is to mkdir -p the paths (after converting to /) and then cp the files to those paths.



But there are a lot of files, and these redundant mkdir -p statements for every file really slows things down.



Is there any more elegant way to convert a zip file with Windows paths to Linux paths?










share|improve this question

























  • Go Back to Windows. Tell whoever creates the Zip File not to use the Native Zip Interface, but a program like 7-Zip, and have them create a tar file. If that can't be done you need to unzip the files while ignoring the path, using the unzip -j -d options. See Forcing Unzip - No Paths

    – eyoung100
    Nov 5 '14 at 17:04











  • Even with -j, I still get filename windowpathseparatormyfile.ext cause Linux/Zip don't treat it as a paths. And I have absolutely no control over the zip file creation.

    – Slav
    Nov 5 '14 at 17:25











  • I have a hunch, that the zip file creator is using the native Windows Zip Interface, i.e, create an empty file and then adding files into the zip file. This method is not portable, as you have discovered. You need to use a program like WinZip or 7-Zip that has a CLI, like Anton used below. I just tried to use Zip.exe and got not recognized.

    – eyoung100
    Nov 5 '14 at 17:35
















4















I have a .zip created on a Windows machine (outside of my control). The zip file contains paths that I need to preserve when I unzip.



However, when I unzip, all files end up like:
unzip_dir/windowpathseparatormyfile.ext



I've tried both, with and without -j option.
My issue is that I need that path information under windowpathseparator. I need that file structure to be created when I unzip.



I can mv the file and flip the to / easily enough in a script, but then there are errors that the destination path directories do not exist. My workaround for now is to mkdir -p the paths (after converting to /) and then cp the files to those paths.



But there are a lot of files, and these redundant mkdir -p statements for every file really slows things down.



Is there any more elegant way to convert a zip file with Windows paths to Linux paths?










share|improve this question

























  • Go Back to Windows. Tell whoever creates the Zip File not to use the Native Zip Interface, but a program like 7-Zip, and have them create a tar file. If that can't be done you need to unzip the files while ignoring the path, using the unzip -j -d options. See Forcing Unzip - No Paths

    – eyoung100
    Nov 5 '14 at 17:04











  • Even with -j, I still get filename windowpathseparatormyfile.ext cause Linux/Zip don't treat it as a paths. And I have absolutely no control over the zip file creation.

    – Slav
    Nov 5 '14 at 17:25











  • I have a hunch, that the zip file creator is using the native Windows Zip Interface, i.e, create an empty file and then adding files into the zip file. This method is not portable, as you have discovered. You need to use a program like WinZip or 7-Zip that has a CLI, like Anton used below. I just tried to use Zip.exe and got not recognized.

    – eyoung100
    Nov 5 '14 at 17:35














4












4








4


2






I have a .zip created on a Windows machine (outside of my control). The zip file contains paths that I need to preserve when I unzip.



However, when I unzip, all files end up like:
unzip_dir/windowpathseparatormyfile.ext



I've tried both, with and without -j option.
My issue is that I need that path information under windowpathseparator. I need that file structure to be created when I unzip.



I can mv the file and flip the to / easily enough in a script, but then there are errors that the destination path directories do not exist. My workaround for now is to mkdir -p the paths (after converting to /) and then cp the files to those paths.



But there are a lot of files, and these redundant mkdir -p statements for every file really slows things down.



Is there any more elegant way to convert a zip file with Windows paths to Linux paths?










share|improve this question
















I have a .zip created on a Windows machine (outside of my control). The zip file contains paths that I need to preserve when I unzip.



However, when I unzip, all files end up like:
unzip_dir/windowpathseparatormyfile.ext



I've tried both, with and without -j option.
My issue is that I need that path information under windowpathseparator. I need that file structure to be created when I unzip.



I can mv the file and flip the to / easily enough in a script, but then there are errors that the destination path directories do not exist. My workaround for now is to mkdir -p the paths (after converting to /) and then cp the files to those paths.



But there are a lot of files, and these redundant mkdir -p statements for every file really slows things down.



Is there any more elegant way to convert a zip file with Windows paths to Linux paths?







filenames zip






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 6 '14 at 23:25









Gilles

541k12810941610




541k12810941610










asked Nov 5 '14 at 16:35









SlavSlav

123115




123115













  • Go Back to Windows. Tell whoever creates the Zip File not to use the Native Zip Interface, but a program like 7-Zip, and have them create a tar file. If that can't be done you need to unzip the files while ignoring the path, using the unzip -j -d options. See Forcing Unzip - No Paths

    – eyoung100
    Nov 5 '14 at 17:04











  • Even with -j, I still get filename windowpathseparatormyfile.ext cause Linux/Zip don't treat it as a paths. And I have absolutely no control over the zip file creation.

    – Slav
    Nov 5 '14 at 17:25











  • I have a hunch, that the zip file creator is using the native Windows Zip Interface, i.e, create an empty file and then adding files into the zip file. This method is not portable, as you have discovered. You need to use a program like WinZip or 7-Zip that has a CLI, like Anton used below. I just tried to use Zip.exe and got not recognized.

    – eyoung100
    Nov 5 '14 at 17:35



















  • Go Back to Windows. Tell whoever creates the Zip File not to use the Native Zip Interface, but a program like 7-Zip, and have them create a tar file. If that can't be done you need to unzip the files while ignoring the path, using the unzip -j -d options. See Forcing Unzip - No Paths

    – eyoung100
    Nov 5 '14 at 17:04











  • Even with -j, I still get filename windowpathseparatormyfile.ext cause Linux/Zip don't treat it as a paths. And I have absolutely no control over the zip file creation.

    – Slav
    Nov 5 '14 at 17:25











  • I have a hunch, that the zip file creator is using the native Windows Zip Interface, i.e, create an empty file and then adding files into the zip file. This method is not portable, as you have discovered. You need to use a program like WinZip or 7-Zip that has a CLI, like Anton used below. I just tried to use Zip.exe and got not recognized.

    – eyoung100
    Nov 5 '14 at 17:35

















Go Back to Windows. Tell whoever creates the Zip File not to use the Native Zip Interface, but a program like 7-Zip, and have them create a tar file. If that can't be done you need to unzip the files while ignoring the path, using the unzip -j -d options. See Forcing Unzip - No Paths

– eyoung100
Nov 5 '14 at 17:04





Go Back to Windows. Tell whoever creates the Zip File not to use the Native Zip Interface, but a program like 7-Zip, and have them create a tar file. If that can't be done you need to unzip the files while ignoring the path, using the unzip -j -d options. See Forcing Unzip - No Paths

– eyoung100
Nov 5 '14 at 17:04













Even with -j, I still get filename windowpathseparatormyfile.ext cause Linux/Zip don't treat it as a paths. And I have absolutely no control over the zip file creation.

– Slav
Nov 5 '14 at 17:25





Even with -j, I still get filename windowpathseparatormyfile.ext cause Linux/Zip don't treat it as a paths. And I have absolutely no control over the zip file creation.

– Slav
Nov 5 '14 at 17:25













I have a hunch, that the zip file creator is using the native Windows Zip Interface, i.e, create an empty file and then adding files into the zip file. This method is not portable, as you have discovered. You need to use a program like WinZip or 7-Zip that has a CLI, like Anton used below. I just tried to use Zip.exe and got not recognized.

– eyoung100
Nov 5 '14 at 17:35





I have a hunch, that the zip file creator is using the native Windows Zip Interface, i.e, create an empty file and then adding files into the zip file. This method is not portable, as you have discovered. You need to use a program like WinZip or 7-Zip that has a CLI, like Anton used below. I just tried to use Zip.exe and got not recognized.

– eyoung100
Nov 5 '14 at 17:35










4 Answers
4






active

oldest

votes


















2














I think something went wrong with the creation of the zip file, because when I create a zip file on Windows is has (portable) forward slashes:



zip.exe -r pip pip
updating: pip/ (244 bytes security) (stored 0%)
adding: pip/pip.log (164 bytes security) (deflated 66%)


But now that you have the files with file names that contain "paths" with backslashes, you can run the following program in unzip_dir:



#! /usr/bin/env python

# already created directories, walk works topdown, so a child dir
# never creates a directory if there is a parent dir with a file.
made_dirs = set()

for root, dir_names, file_names in os.walk('.'):
for file_name in file_names:
if '\' not in file_name:
continue
alt_file_name = file_name.replace('\', '/')
if alt_file_name.startswith('/'):
alt_file_name = alt_file_name[1:] # cut of starting dir separator
alt_dir_name, alt_base_name = alt_file_name.rsplit('/', 1)
print 'alt_dir', alt_dir_name
full_dir_name = os.path.join(root, alt_dir_name)
if full_dir_name not in made_dirs:
os.makedirs(full_dir_name) # only create if not done yet
made_dirs.add(full_dir_name)
os.rename(os.path.join(root, file_name),
os.path.join(root, alt_file_name))


This handles files in any directory under the directory from where the program is started. Given the problem that you describe, the unzip_dir probably doesn't have any subdirectories to start with, and the program could just walk over the files in the current directory only.






share|improve this answer


























  • This is pretty much what I am doing in shell, but there are a lot of files (and not that many directories), so there are a lot of redundant os.makedirs(os.path.join(root, alt_dir_name)) statements, and the script really seems to slow down around that block

    – Slav
    Nov 6 '14 at 15:57











  • @Slav actually with 2 files in the same directory the script gave an error. I now only make each directory once. The names are cached in memory in the set made_dirs. That way it doesn't try, or even have to check the disk for files in the same directory. This could be optimized some more if necessary, as makedirs() actually excepts on all the intermediate directories. That makes sense if most files live alone in a separate directory.

    – Anthon
    Nov 6 '14 at 16:11













  • That last sentence of the previous comment refers to the optimization.

    – Anthon
    Nov 6 '14 at 16:21











  • The script errored becase a folder already existed. I replaced the line os.makedirs(full_dir_name) with try: os.makedirs(full_dir_name) except OSError as exc: if exc.errno == errno.EEXIST and os.path.isdir(full_dir_name): # the pass already exists and is a folder, let's just ignore it pass else: raise

    – madmuffin
    Aug 18 '16 at 13:01













  • Note: The script is missing an import os to be able to run out of the box.

    – madmuffin
    Aug 18 '16 at 13:03



















4














Use 7z rn to rename the files within the archive so that they have a forward slash. Then when you extract the archive, directories will be created.



To rename the files, list the paths of the files within the archive containing slashes, and generate a list of replacement strings that change the backslash to a slash using awk, for example.



7z rn windows.zip $(7z l windows.zip | grep '\' | awk '{ print $6, gensub(/\/, "/", "g", $6); }' | paste -s)





share|improve this answer































    2














    This is just an update of @anton's answer which includes fixes by @madmuffin (FileExistsError: [Errno 17] File exists and missing os module import), a fix for python 3 (SyntaxError: Missing parentheses in call to 'print') and a fix for the missing errno module import (NameError: name 'errno' is not defined).



    #! /usr/bin/env python

    import os
    import errno

    # already created directories, walk works topdown, so a child dir
    # never creates a directory if there is a parent dir with a file.
    made_dirs = set()

    for root, dir_names, file_names in os.walk('.'):
    for file_name in file_names:
    if '\' not in file_name:
    continue
    alt_file_name = file_name.replace('\', '/')
    if alt_file_name.startswith('/'):
    alt_file_name = alt_file_name[1:] # cut of starting dir separator
    alt_dir_name, alt_base_name = alt_file_name.rsplit('/', 1)
    print('alt_dir', alt_dir_name)
    full_dir_name = os.path.join(root, alt_dir_name)
    if full_dir_name not in made_dirs:
    try:
    os.makedirs(full_dir_name)
    except OSError as exc:
    if exc.errno == errno.EEXIST and os.path.isdir(full_dir_name):
    # the pass already exists and is a folder, let's just ignore it
    pass
    else:
    raise
    made_dirs.add(full_dir_name)
    os.rename(os.path.join(root, file_name),
    os.path.join(root, alt_file_name))





    share|improve this answer
























    • anton and madmuffin, thank you for the original nice little script

      – Daishi
      May 18 '17 at 0:31











    • with all those updates, I feel like I'm in need of a github feature here

      – Daishi
      May 18 '17 at 0:32











    • @anton I whish you gave a meaningful name to this script. Now I'm stuck trying to find one ;)

      – Daishi
      May 18 '17 at 0:36





















    0














    Had to make a few changes to @xn.'s answer for Mac. This worked for me:




    1. brew install gawk

    2. 7z rn windows.zip $(7z l windows.zip | grep '\' | gawk '{ print $6, gensub(/\/, "/", "g", $6); }' | paste -s -)






    share|improve this answer























      Your Answer








      StackExchange.ready(function() {
      var channelOptions = {
      tags: "".split(" "),
      id: "106"
      };
      initTagRenderer("".split(" "), "".split(" "), channelOptions);

      StackExchange.using("externalEditor", function() {
      // Have to fire editor after snippets, if snippets enabled
      if (StackExchange.settings.snippets.snippetsEnabled) {
      StackExchange.using("snippets", function() {
      createEditor();
      });
      }
      else {
      createEditor();
      }
      });

      function createEditor() {
      StackExchange.prepareEditor({
      heartbeatType: 'answer',
      autoActivateHeartbeat: false,
      convertImagesToLinks: false,
      noModals: true,
      showLowRepImageUploadWarning: true,
      reputationToPostImages: null,
      bindNavPrevention: true,
      postfix: "",
      imageUploader: {
      brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
      contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
      allowUrls: true
      },
      onDemand: true,
      discardSelector: ".discard-answer"
      ,immediatelyShowMarkdownHelp:true
      });


      }
      });














      draft saved

      draft discarded


















      StackExchange.ready(
      function () {
      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f166159%2fconvert-a-windows-created-zip-to-linux-internal-paths-issue%23new-answer', 'question_page');
      }
      );

      Post as a guest















      Required, but never shown

























      4 Answers
      4






      active

      oldest

      votes








      4 Answers
      4






      active

      oldest

      votes









      active

      oldest

      votes






      active

      oldest

      votes









      2














      I think something went wrong with the creation of the zip file, because when I create a zip file on Windows is has (portable) forward slashes:



      zip.exe -r pip pip
      updating: pip/ (244 bytes security) (stored 0%)
      adding: pip/pip.log (164 bytes security) (deflated 66%)


      But now that you have the files with file names that contain "paths" with backslashes, you can run the following program in unzip_dir:



      #! /usr/bin/env python

      # already created directories, walk works topdown, so a child dir
      # never creates a directory if there is a parent dir with a file.
      made_dirs = set()

      for root, dir_names, file_names in os.walk('.'):
      for file_name in file_names:
      if '\' not in file_name:
      continue
      alt_file_name = file_name.replace('\', '/')
      if alt_file_name.startswith('/'):
      alt_file_name = alt_file_name[1:] # cut of starting dir separator
      alt_dir_name, alt_base_name = alt_file_name.rsplit('/', 1)
      print 'alt_dir', alt_dir_name
      full_dir_name = os.path.join(root, alt_dir_name)
      if full_dir_name not in made_dirs:
      os.makedirs(full_dir_name) # only create if not done yet
      made_dirs.add(full_dir_name)
      os.rename(os.path.join(root, file_name),
      os.path.join(root, alt_file_name))


      This handles files in any directory under the directory from where the program is started. Given the problem that you describe, the unzip_dir probably doesn't have any subdirectories to start with, and the program could just walk over the files in the current directory only.






      share|improve this answer


























      • This is pretty much what I am doing in shell, but there are a lot of files (and not that many directories), so there are a lot of redundant os.makedirs(os.path.join(root, alt_dir_name)) statements, and the script really seems to slow down around that block

        – Slav
        Nov 6 '14 at 15:57











      • @Slav actually with 2 files in the same directory the script gave an error. I now only make each directory once. The names are cached in memory in the set made_dirs. That way it doesn't try, or even have to check the disk for files in the same directory. This could be optimized some more if necessary, as makedirs() actually excepts on all the intermediate directories. That makes sense if most files live alone in a separate directory.

        – Anthon
        Nov 6 '14 at 16:11













      • That last sentence of the previous comment refers to the optimization.

        – Anthon
        Nov 6 '14 at 16:21











      • The script errored becase a folder already existed. I replaced the line os.makedirs(full_dir_name) with try: os.makedirs(full_dir_name) except OSError as exc: if exc.errno == errno.EEXIST and os.path.isdir(full_dir_name): # the pass already exists and is a folder, let's just ignore it pass else: raise

        – madmuffin
        Aug 18 '16 at 13:01













      • Note: The script is missing an import os to be able to run out of the box.

        – madmuffin
        Aug 18 '16 at 13:03
















      2














      I think something went wrong with the creation of the zip file, because when I create a zip file on Windows is has (portable) forward slashes:



      zip.exe -r pip pip
      updating: pip/ (244 bytes security) (stored 0%)
      adding: pip/pip.log (164 bytes security) (deflated 66%)


      But now that you have the files with file names that contain "paths" with backslashes, you can run the following program in unzip_dir:



      #! /usr/bin/env python

      # already created directories, walk works topdown, so a child dir
      # never creates a directory if there is a parent dir with a file.
      made_dirs = set()

      for root, dir_names, file_names in os.walk('.'):
      for file_name in file_names:
      if '\' not in file_name:
      continue
      alt_file_name = file_name.replace('\', '/')
      if alt_file_name.startswith('/'):
      alt_file_name = alt_file_name[1:] # cut of starting dir separator
      alt_dir_name, alt_base_name = alt_file_name.rsplit('/', 1)
      print 'alt_dir', alt_dir_name
      full_dir_name = os.path.join(root, alt_dir_name)
      if full_dir_name not in made_dirs:
      os.makedirs(full_dir_name) # only create if not done yet
      made_dirs.add(full_dir_name)
      os.rename(os.path.join(root, file_name),
      os.path.join(root, alt_file_name))


      This handles files in any directory under the directory from where the program is started. Given the problem that you describe, the unzip_dir probably doesn't have any subdirectories to start with, and the program could just walk over the files in the current directory only.






      share|improve this answer


























      • This is pretty much what I am doing in shell, but there are a lot of files (and not that many directories), so there are a lot of redundant os.makedirs(os.path.join(root, alt_dir_name)) statements, and the script really seems to slow down around that block

        – Slav
        Nov 6 '14 at 15:57











      • @Slav actually with 2 files in the same directory the script gave an error. I now only make each directory once. The names are cached in memory in the set made_dirs. That way it doesn't try, or even have to check the disk for files in the same directory. This could be optimized some more if necessary, as makedirs() actually excepts on all the intermediate directories. That makes sense if most files live alone in a separate directory.

        – Anthon
        Nov 6 '14 at 16:11













      • That last sentence of the previous comment refers to the optimization.

        – Anthon
        Nov 6 '14 at 16:21











      • The script errored becase a folder already existed. I replaced the line os.makedirs(full_dir_name) with try: os.makedirs(full_dir_name) except OSError as exc: if exc.errno == errno.EEXIST and os.path.isdir(full_dir_name): # the pass already exists and is a folder, let's just ignore it pass else: raise

        – madmuffin
        Aug 18 '16 at 13:01













      • Note: The script is missing an import os to be able to run out of the box.

        – madmuffin
        Aug 18 '16 at 13:03














      2












      2








      2







      I think something went wrong with the creation of the zip file, because when I create a zip file on Windows is has (portable) forward slashes:



      zip.exe -r pip pip
      updating: pip/ (244 bytes security) (stored 0%)
      adding: pip/pip.log (164 bytes security) (deflated 66%)


      But now that you have the files with file names that contain "paths" with backslashes, you can run the following program in unzip_dir:



      #! /usr/bin/env python

      # already created directories, walk works topdown, so a child dir
      # never creates a directory if there is a parent dir with a file.
      made_dirs = set()

      for root, dir_names, file_names in os.walk('.'):
      for file_name in file_names:
      if '\' not in file_name:
      continue
      alt_file_name = file_name.replace('\', '/')
      if alt_file_name.startswith('/'):
      alt_file_name = alt_file_name[1:] # cut of starting dir separator
      alt_dir_name, alt_base_name = alt_file_name.rsplit('/', 1)
      print 'alt_dir', alt_dir_name
      full_dir_name = os.path.join(root, alt_dir_name)
      if full_dir_name not in made_dirs:
      os.makedirs(full_dir_name) # only create if not done yet
      made_dirs.add(full_dir_name)
      os.rename(os.path.join(root, file_name),
      os.path.join(root, alt_file_name))


      This handles files in any directory under the directory from where the program is started. Given the problem that you describe, the unzip_dir probably doesn't have any subdirectories to start with, and the program could just walk over the files in the current directory only.






      share|improve this answer















      I think something went wrong with the creation of the zip file, because when I create a zip file on Windows is has (portable) forward slashes:



      zip.exe -r pip pip
      updating: pip/ (244 bytes security) (stored 0%)
      adding: pip/pip.log (164 bytes security) (deflated 66%)


      But now that you have the files with file names that contain "paths" with backslashes, you can run the following program in unzip_dir:



      #! /usr/bin/env python

      # already created directories, walk works topdown, so a child dir
      # never creates a directory if there is a parent dir with a file.
      made_dirs = set()

      for root, dir_names, file_names in os.walk('.'):
      for file_name in file_names:
      if '\' not in file_name:
      continue
      alt_file_name = file_name.replace('\', '/')
      if alt_file_name.startswith('/'):
      alt_file_name = alt_file_name[1:] # cut of starting dir separator
      alt_dir_name, alt_base_name = alt_file_name.rsplit('/', 1)
      print 'alt_dir', alt_dir_name
      full_dir_name = os.path.join(root, alt_dir_name)
      if full_dir_name not in made_dirs:
      os.makedirs(full_dir_name) # only create if not done yet
      made_dirs.add(full_dir_name)
      os.rename(os.path.join(root, file_name),
      os.path.join(root, alt_file_name))


      This handles files in any directory under the directory from where the program is started. Given the problem that you describe, the unzip_dir probably doesn't have any subdirectories to start with, and the program could just walk over the files in the current directory only.







      share|improve this answer














      share|improve this answer



      share|improve this answer








      edited Nov 6 '14 at 16:10

























      answered Nov 5 '14 at 17:09









      AnthonAnthon

      61k17104166




      61k17104166













      • This is pretty much what I am doing in shell, but there are a lot of files (and not that many directories), so there are a lot of redundant os.makedirs(os.path.join(root, alt_dir_name)) statements, and the script really seems to slow down around that block

        – Slav
        Nov 6 '14 at 15:57











      • @Slav actually with 2 files in the same directory the script gave an error. I now only make each directory once. The names are cached in memory in the set made_dirs. That way it doesn't try, or even have to check the disk for files in the same directory. This could be optimized some more if necessary, as makedirs() actually excepts on all the intermediate directories. That makes sense if most files live alone in a separate directory.

        – Anthon
        Nov 6 '14 at 16:11













      • That last sentence of the previous comment refers to the optimization.

        – Anthon
        Nov 6 '14 at 16:21











      • The script errored becase a folder already existed. I replaced the line os.makedirs(full_dir_name) with try: os.makedirs(full_dir_name) except OSError as exc: if exc.errno == errno.EEXIST and os.path.isdir(full_dir_name): # the pass already exists and is a folder, let's just ignore it pass else: raise

        – madmuffin
        Aug 18 '16 at 13:01













      • Note: The script is missing an import os to be able to run out of the box.

        – madmuffin
        Aug 18 '16 at 13:03



















      • This is pretty much what I am doing in shell, but there are a lot of files (and not that many directories), so there are a lot of redundant os.makedirs(os.path.join(root, alt_dir_name)) statements, and the script really seems to slow down around that block

        – Slav
        Nov 6 '14 at 15:57











      • @Slav actually with 2 files in the same directory the script gave an error. I now only make each directory once. The names are cached in memory in the set made_dirs. That way it doesn't try, or even have to check the disk for files in the same directory. This could be optimized some more if necessary, as makedirs() actually excepts on all the intermediate directories. That makes sense if most files live alone in a separate directory.

        – Anthon
        Nov 6 '14 at 16:11













      • That last sentence of the previous comment refers to the optimization.

        – Anthon
        Nov 6 '14 at 16:21











      • The script errored becase a folder already existed. I replaced the line os.makedirs(full_dir_name) with try: os.makedirs(full_dir_name) except OSError as exc: if exc.errno == errno.EEXIST and os.path.isdir(full_dir_name): # the pass already exists and is a folder, let's just ignore it pass else: raise

        – madmuffin
        Aug 18 '16 at 13:01













      • Note: The script is missing an import os to be able to run out of the box.

        – madmuffin
        Aug 18 '16 at 13:03

















      This is pretty much what I am doing in shell, but there are a lot of files (and not that many directories), so there are a lot of redundant os.makedirs(os.path.join(root, alt_dir_name)) statements, and the script really seems to slow down around that block

      – Slav
      Nov 6 '14 at 15:57





      This is pretty much what I am doing in shell, but there are a lot of files (and not that many directories), so there are a lot of redundant os.makedirs(os.path.join(root, alt_dir_name)) statements, and the script really seems to slow down around that block

      – Slav
      Nov 6 '14 at 15:57













      @Slav actually with 2 files in the same directory the script gave an error. I now only make each directory once. The names are cached in memory in the set made_dirs. That way it doesn't try, or even have to check the disk for files in the same directory. This could be optimized some more if necessary, as makedirs() actually excepts on all the intermediate directories. That makes sense if most files live alone in a separate directory.

      – Anthon
      Nov 6 '14 at 16:11







      @Slav actually with 2 files in the same directory the script gave an error. I now only make each directory once. The names are cached in memory in the set made_dirs. That way it doesn't try, or even have to check the disk for files in the same directory. This could be optimized some more if necessary, as makedirs() actually excepts on all the intermediate directories. That makes sense if most files live alone in a separate directory.

      – Anthon
      Nov 6 '14 at 16:11















      That last sentence of the previous comment refers to the optimization.

      – Anthon
      Nov 6 '14 at 16:21





      That last sentence of the previous comment refers to the optimization.

      – Anthon
      Nov 6 '14 at 16:21













      The script errored becase a folder already existed. I replaced the line os.makedirs(full_dir_name) with try: os.makedirs(full_dir_name) except OSError as exc: if exc.errno == errno.EEXIST and os.path.isdir(full_dir_name): # the pass already exists and is a folder, let's just ignore it pass else: raise

      – madmuffin
      Aug 18 '16 at 13:01







      The script errored becase a folder already existed. I replaced the line os.makedirs(full_dir_name) with try: os.makedirs(full_dir_name) except OSError as exc: if exc.errno == errno.EEXIST and os.path.isdir(full_dir_name): # the pass already exists and is a folder, let's just ignore it pass else: raise

      – madmuffin
      Aug 18 '16 at 13:01















      Note: The script is missing an import os to be able to run out of the box.

      – madmuffin
      Aug 18 '16 at 13:03





      Note: The script is missing an import os to be able to run out of the box.

      – madmuffin
      Aug 18 '16 at 13:03













      4














      Use 7z rn to rename the files within the archive so that they have a forward slash. Then when you extract the archive, directories will be created.



      To rename the files, list the paths of the files within the archive containing slashes, and generate a list of replacement strings that change the backslash to a slash using awk, for example.



      7z rn windows.zip $(7z l windows.zip | grep '\' | awk '{ print $6, gensub(/\/, "/", "g", $6); }' | paste -s)





      share|improve this answer




























        4














        Use 7z rn to rename the files within the archive so that they have a forward slash. Then when you extract the archive, directories will be created.



        To rename the files, list the paths of the files within the archive containing slashes, and generate a list of replacement strings that change the backslash to a slash using awk, for example.



        7z rn windows.zip $(7z l windows.zip | grep '\' | awk '{ print $6, gensub(/\/, "/", "g", $6); }' | paste -s)





        share|improve this answer


























          4












          4








          4







          Use 7z rn to rename the files within the archive so that they have a forward slash. Then when you extract the archive, directories will be created.



          To rename the files, list the paths of the files within the archive containing slashes, and generate a list of replacement strings that change the backslash to a slash using awk, for example.



          7z rn windows.zip $(7z l windows.zip | grep '\' | awk '{ print $6, gensub(/\/, "/", "g", $6); }' | paste -s)





          share|improve this answer













          Use 7z rn to rename the files within the archive so that they have a forward slash. Then when you extract the archive, directories will be created.



          To rename the files, list the paths of the files within the archive containing slashes, and generate a list of replacement strings that change the backslash to a slash using awk, for example.



          7z rn windows.zip $(7z l windows.zip | grep '\' | awk '{ print $6, gensub(/\/, "/", "g", $6); }' | paste -s)






          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Jul 6 '17 at 20:42









          xn.xn.

          1734




          1734























              2














              This is just an update of @anton's answer which includes fixes by @madmuffin (FileExistsError: [Errno 17] File exists and missing os module import), a fix for python 3 (SyntaxError: Missing parentheses in call to 'print') and a fix for the missing errno module import (NameError: name 'errno' is not defined).



              #! /usr/bin/env python

              import os
              import errno

              # already created directories, walk works topdown, so a child dir
              # never creates a directory if there is a parent dir with a file.
              made_dirs = set()

              for root, dir_names, file_names in os.walk('.'):
              for file_name in file_names:
              if '\' not in file_name:
              continue
              alt_file_name = file_name.replace('\', '/')
              if alt_file_name.startswith('/'):
              alt_file_name = alt_file_name[1:] # cut of starting dir separator
              alt_dir_name, alt_base_name = alt_file_name.rsplit('/', 1)
              print('alt_dir', alt_dir_name)
              full_dir_name = os.path.join(root, alt_dir_name)
              if full_dir_name not in made_dirs:
              try:
              os.makedirs(full_dir_name)
              except OSError as exc:
              if exc.errno == errno.EEXIST and os.path.isdir(full_dir_name):
              # the pass already exists and is a folder, let's just ignore it
              pass
              else:
              raise
              made_dirs.add(full_dir_name)
              os.rename(os.path.join(root, file_name),
              os.path.join(root, alt_file_name))





              share|improve this answer
























              • anton and madmuffin, thank you for the original nice little script

                – Daishi
                May 18 '17 at 0:31











              • with all those updates, I feel like I'm in need of a github feature here

                – Daishi
                May 18 '17 at 0:32











              • @anton I whish you gave a meaningful name to this script. Now I'm stuck trying to find one ;)

                – Daishi
                May 18 '17 at 0:36


















              2














              This is just an update of @anton's answer which includes fixes by @madmuffin (FileExistsError: [Errno 17] File exists and missing os module import), a fix for python 3 (SyntaxError: Missing parentheses in call to 'print') and a fix for the missing errno module import (NameError: name 'errno' is not defined).



              #! /usr/bin/env python

              import os
              import errno

              # already created directories, walk works topdown, so a child dir
              # never creates a directory if there is a parent dir with a file.
              made_dirs = set()

              for root, dir_names, file_names in os.walk('.'):
              for file_name in file_names:
              if '\' not in file_name:
              continue
              alt_file_name = file_name.replace('\', '/')
              if alt_file_name.startswith('/'):
              alt_file_name = alt_file_name[1:] # cut of starting dir separator
              alt_dir_name, alt_base_name = alt_file_name.rsplit('/', 1)
              print('alt_dir', alt_dir_name)
              full_dir_name = os.path.join(root, alt_dir_name)
              if full_dir_name not in made_dirs:
              try:
              os.makedirs(full_dir_name)
              except OSError as exc:
              if exc.errno == errno.EEXIST and os.path.isdir(full_dir_name):
              # the pass already exists and is a folder, let's just ignore it
              pass
              else:
              raise
              made_dirs.add(full_dir_name)
              os.rename(os.path.join(root, file_name),
              os.path.join(root, alt_file_name))





              share|improve this answer
























              • anton and madmuffin, thank you for the original nice little script

                – Daishi
                May 18 '17 at 0:31











              • with all those updates, I feel like I'm in need of a github feature here

                – Daishi
                May 18 '17 at 0:32











              • @anton I whish you gave a meaningful name to this script. Now I'm stuck trying to find one ;)

                – Daishi
                May 18 '17 at 0:36
















              2












              2








              2







              This is just an update of @anton's answer which includes fixes by @madmuffin (FileExistsError: [Errno 17] File exists and missing os module import), a fix for python 3 (SyntaxError: Missing parentheses in call to 'print') and a fix for the missing errno module import (NameError: name 'errno' is not defined).



              #! /usr/bin/env python

              import os
              import errno

              # already created directories, walk works topdown, so a child dir
              # never creates a directory if there is a parent dir with a file.
              made_dirs = set()

              for root, dir_names, file_names in os.walk('.'):
              for file_name in file_names:
              if '\' not in file_name:
              continue
              alt_file_name = file_name.replace('\', '/')
              if alt_file_name.startswith('/'):
              alt_file_name = alt_file_name[1:] # cut of starting dir separator
              alt_dir_name, alt_base_name = alt_file_name.rsplit('/', 1)
              print('alt_dir', alt_dir_name)
              full_dir_name = os.path.join(root, alt_dir_name)
              if full_dir_name not in made_dirs:
              try:
              os.makedirs(full_dir_name)
              except OSError as exc:
              if exc.errno == errno.EEXIST and os.path.isdir(full_dir_name):
              # the pass already exists and is a folder, let's just ignore it
              pass
              else:
              raise
              made_dirs.add(full_dir_name)
              os.rename(os.path.join(root, file_name),
              os.path.join(root, alt_file_name))





              share|improve this answer













              This is just an update of @anton's answer which includes fixes by @madmuffin (FileExistsError: [Errno 17] File exists and missing os module import), a fix for python 3 (SyntaxError: Missing parentheses in call to 'print') and a fix for the missing errno module import (NameError: name 'errno' is not defined).



              #! /usr/bin/env python

              import os
              import errno

              # already created directories, walk works topdown, so a child dir
              # never creates a directory if there is a parent dir with a file.
              made_dirs = set()

              for root, dir_names, file_names in os.walk('.'):
              for file_name in file_names:
              if '\' not in file_name:
              continue
              alt_file_name = file_name.replace('\', '/')
              if alt_file_name.startswith('/'):
              alt_file_name = alt_file_name[1:] # cut of starting dir separator
              alt_dir_name, alt_base_name = alt_file_name.rsplit('/', 1)
              print('alt_dir', alt_dir_name)
              full_dir_name = os.path.join(root, alt_dir_name)
              if full_dir_name not in made_dirs:
              try:
              os.makedirs(full_dir_name)
              except OSError as exc:
              if exc.errno == errno.EEXIST and os.path.isdir(full_dir_name):
              # the pass already exists and is a folder, let's just ignore it
              pass
              else:
              raise
              made_dirs.add(full_dir_name)
              os.rename(os.path.join(root, file_name),
              os.path.join(root, alt_file_name))






              share|improve this answer












              share|improve this answer



              share|improve this answer










              answered May 18 '17 at 0:30









              DaishiDaishi

              1862




              1862













              • anton and madmuffin, thank you for the original nice little script

                – Daishi
                May 18 '17 at 0:31











              • with all those updates, I feel like I'm in need of a github feature here

                – Daishi
                May 18 '17 at 0:32











              • @anton I whish you gave a meaningful name to this script. Now I'm stuck trying to find one ;)

                – Daishi
                May 18 '17 at 0:36





















              • anton and madmuffin, thank you for the original nice little script

                – Daishi
                May 18 '17 at 0:31











              • with all those updates, I feel like I'm in need of a github feature here

                – Daishi
                May 18 '17 at 0:32











              • @anton I whish you gave a meaningful name to this script. Now I'm stuck trying to find one ;)

                – Daishi
                May 18 '17 at 0:36



















              anton and madmuffin, thank you for the original nice little script

              – Daishi
              May 18 '17 at 0:31





              anton and madmuffin, thank you for the original nice little script

              – Daishi
              May 18 '17 at 0:31













              with all those updates, I feel like I'm in need of a github feature here

              – Daishi
              May 18 '17 at 0:32





              with all those updates, I feel like I'm in need of a github feature here

              – Daishi
              May 18 '17 at 0:32













              @anton I whish you gave a meaningful name to this script. Now I'm stuck trying to find one ;)

              – Daishi
              May 18 '17 at 0:36







              @anton I whish you gave a meaningful name to this script. Now I'm stuck trying to find one ;)

              – Daishi
              May 18 '17 at 0:36













              0














              Had to make a few changes to @xn.'s answer for Mac. This worked for me:




              1. brew install gawk

              2. 7z rn windows.zip $(7z l windows.zip | grep '\' | gawk '{ print $6, gensub(/\/, "/", "g", $6); }' | paste -s -)






              share|improve this answer




























                0














                Had to make a few changes to @xn.'s answer for Mac. This worked for me:




                1. brew install gawk

                2. 7z rn windows.zip $(7z l windows.zip | grep '\' | gawk '{ print $6, gensub(/\/, "/", "g", $6); }' | paste -s -)






                share|improve this answer


























                  0












                  0








                  0







                  Had to make a few changes to @xn.'s answer for Mac. This worked for me:




                  1. brew install gawk

                  2. 7z rn windows.zip $(7z l windows.zip | grep '\' | gawk '{ print $6, gensub(/\/, "/", "g", $6); }' | paste -s -)






                  share|improve this answer













                  Had to make a few changes to @xn.'s answer for Mac. This worked for me:




                  1. brew install gawk

                  2. 7z rn windows.zip $(7z l windows.zip | grep '\' | gawk '{ print $6, gensub(/\/, "/", "g", $6); }' | paste -s -)







                  share|improve this answer












                  share|improve this answer



                  share|improve this answer










                  answered Feb 19 at 4:04









                  DozyBratDozyBrat

                  1




                  1






























                      draft saved

                      draft discarded




















































                      Thanks for contributing an answer to Unix & Linux Stack Exchange!


                      • Please be sure to answer the question. Provide details and share your research!

                      But avoid



                      • Asking for help, clarification, or responding to other answers.

                      • Making statements based on opinion; back them up with references or personal experience.


                      To learn more, see our tips on writing great answers.




                      draft saved


                      draft discarded














                      StackExchange.ready(
                      function () {
                      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f166159%2fconvert-a-windows-created-zip-to-linux-internal-paths-issue%23new-answer', 'question_page');
                      }
                      );

                      Post as a guest















                      Required, but never shown





















































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown

































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown







                      Popular posts from this blog

                      How to make a Squid Proxy server?

                      Is this a new Fibonacci Identity?

                      19世紀