Answers.Body: <pre><code>zip -X0 "my.epub" "mimetype"
  zip -Xr "my.epub" "META-INF/" "OEBPS/"
  </code></pre>
  
  <p>As palacsint already pointed out, without the -X flag, one would run into the epubcheck error PKG_005</p>
  
  <pre><code>"The mimetype file has an extra field of length %1$s. The use of the extra field feature of the ZIP format is not permitted for the mimetype file."
  </code></pre>
  
  <p>because the mimetype file is being used as magical number within the compressed zip file, and the zip extra field feature (where zip programs and operating systems can place non-standardized data) would destroy the magical number mechanism (see <a href="https://github.com/IDPF/epubcheck/pull/497" rel="noreferrer">https://github.com/IDPF/epubcheck/pull/497</a>). The -0 flag makes sure that the mimetype file doesn't get compressed, which is also necessary for the mimetype file to work as a magical number, otherwise the data at the position where the mimetype file is expected could be compressed, scrambled gibberish.</p>
  
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2015-09-19T09:18:30.967Z
Answers.LastActivityDate: 2015-09-19T09:18:30.967Z
Answers.UserDisplayName: skreutzer
Answers.Body: <p>A one-liner based on the previous answers, which will take the current dirname as the epub name, and the contents of the current dir as the epub: <code>zip -rX "../$(basename "$(realpath .)").epub" mimetype $(ls|xargs echo|sed 's/mimetype//g')</code></p>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2019-02-21T20:24:45.793Z
Answers.Text: On a Mac, `realpath` is not available by default and you'll want to exclude the invisible `.DS_Store` files… Making the command: `zip -rX "../myprecious.epub" mimetype $(ls|xargs echo|sed 's/mimetype//g') -x *.DS_Store`.
Answers.UserDisplayName: Fabien Snauwaert
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2023-03-04T16:46:23.510Z
Answers.Text: To exclude any DS_Store in any directory use this pattern with the answer from @FabienSnauwaert `**/.DS_Store`
Answers.UserDisplayName: ow3n
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2017-06-26T02:01:09.603Z
Answers.LastActivityDate: 2017-06-26T02:01:09.603Z
Answers.UserDisplayName: geek1011
Answers.Body: <p>I'm using this python script to batch repackage the files.</p>
  <pre><code>import os
  import shutil
  import zipfile
  
  # Enter the paths
  path_to_files = &quot;/Users/matteo/Desktop/ebooks&quot;   # Path to directory containing epub packages
  path_to_new_files = &quot;/Users/matteo/Desktop/ebooks_conv&quot;   # Path to store new epub files in
  
  # Function to store all filenames in a list
  def extract_filename(path_to_files):
      filenames = []
      for f in os.listdir(path_to_files):
          f_name, f_ext = os.path.splitext(f)
          if f_ext == &quot;.epub&quot;:
              filenames.append(f_name)
      filenames.sort()
      return filenames
  
  # Function to generate new epub files
  def create_epub(filenames, path_to_files, path_to_new_files):
      total_files = len(filenames)
      for i, filename in enumerate(filenames, 1):
          epub_path = os.path.join(path_to_files, filename + &quot;.epub&quot;)
          
          # Remove iTunesMetadata.plist if exists
          plist_path = os.path.join(path_to_files, &quot;iTunesMetadata.plist&quot;)
          if os.path.exists(plist_path):
              os.remove(plist_path)
          
          # Copy the EPUB files to a temporary directory to avoid zipping recursively
          temp_dir = os.path.join(path_to_new_files, filename)
          shutil.copytree(epub_path, temp_dir)
          
          # Create the new EPUB archive
          with zipfile.ZipFile(os.path.join(path_to_new_files, filename + &quot;.epub&quot;), 'w') as new_epub:
              for root, dirs, files in os.walk(temp_dir):
                  for file in files:
                      file_path = os.path.join(root, file)
                      # Write each file to the archive
                      new_epub.write(file_path, os.path.relpath(file_path, temp_dir))
          
          # Clean up the temporary directory
          shutil.rmtree(temp_dir)
          
          print(&quot;File #&quot;, i, &quot; has been processed successfully. Remaining files:&quot;, total_files - i)
  
  filenames = extract_filename(path_to_files)
  create_epub(filenames, path_to_files, path_to_new_files)
  </code></pre>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2024-04-18T11:20:33.580Z
Answers.LastActivityDate: 2024-04-18T11:20:33.580Z
Answers.UserDisplayName: Matteo Curcio
Answers.Body: <pre><code>zip -rX ../my.epub mimetype META-INF/ OEBPS/
  </code></pre>
  
  <hr>
  
  <p>Without <code>-X</code> you could get the following when validating it with EpubCheck:</p>
  
  <pre><code>ERROR: my.epub: Mimetype entry must not have an extra field in its ZIP header
  </code></pre>
  
  <p>If <code>mimetype</code> is not the first in the <code>epub</code> file EpubCheck prints the following:</p>
  
  <pre><code>ERROR: my.epub: Mimetype entry missing or not the first in archive
  </code></pre>
  
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2013-12-21T11:11:21.237Z
Answers.LastActivityDate: 2013-12-21T11:11:21.237Z
Answers.UserDisplayName: palacsint
Body: <p>I unzipped an <code>epub</code> file to make some minor modifications. How can I repack it properly to be a valid <code>epub</code> file from command line on Linux?</p>
  
Tags: <epub><linux>
Title: How to repack an epub file from command line
UserDisplayName: palacsint
ThreadText: # How to repack an epub file from command line
  
  (Asked by: username_0 on 2013-12-21)
  
  I unzipped an `epub` file to make some minor modifications. How can I repack it properly to be a valid `epub` file from command line on Linux?
  
  **Tags:** epub, linux
  
  
  ---
  
  ## 4 answers
  
  ### Answer by username_0 on 2013-12-21. Score: 33 | Accepted answer
  
  ```
  zip -rX ../my.epub mimetype META-INF/ OEBPS/
  
  ```
  
  ---
  
  Without `-X` you could get the following when validating it with EpubCheck:
  
  ```
  ERROR: my.epub: Mimetype entry must not have an extra field in its ZIP header
  
  ```
  
  If `mimetype` is not the first in the `epub` file EpubCheck prints the following:
  
  ```
  ERROR: my.epub: Mimetype entry missing or not the first in archive
  
  ```
  
  
  ---
  
  ### Answer by username_1 on 2015-09-19. Score: 7
  
  ```
  zip -X0 "my.epub" "mimetype"
  zip -Xr "my.epub" "META-INF/" "OEBPS/"
  
  ```
  
  As username_0 already pointed out, without the -X flag, one would run into the epubcheck error PKG\_005
  
  ```
  "The mimetype file has an extra field of length %1$s. The use of the extra field feature of the ZIP format is not permitted for the mimetype file."
  
  ```
  
  because the mimetype file is being used as magical number within the compressed zip file, and the zip extra field feature (where zip programs and operating systems can place non-standardized data) would destroy the magical number mechanism (see <https://github.com/IDPF/epubcheck/pull/497>). The -0 flag makes sure that the mimetype file doesn't get compressed, which is also necessary for the mimetype file to work as a magical number, otherwise the data at the position where the mimetype file is expected could be compressed, scrambled gibberish.
  
  
  ---
  
  ### Answer by username_2 on 2017-06-26. Score: 2
  
  A one-liner based on the previous answers, which will take the current dirname as the epub name, and the contents of the current dir as the epub: `zip -rX "../$(basename "$(realpath .)").epub" mimetype $(ls|xargs echo|sed 's/mimetype//g')`
  
  > **Comments:**
  > **username_3**: On a Mac, `realpath` is not available by default and you'll want to exclude the invisible `.DS_Store` files… Making the command: `zip -rX "../myprecious.epub" mimetype $(ls|xargs echo|sed 's/mimetype//g') -x *.DS_Store`.  
  > **username_4**: To exclude any DS_Store in any directory use this pattern with the answer from @username_3 `**/.DS_Store`  
  
  ---
  
  ### Answer by username_5 on 2024-04-18. Score: 0
  
  I'm using this python script to batch repackage the files.
  
  ```
  import os
  import shutil
  import zipfile
  
  # Enter the paths
  path_to_files = "/Users/username_5/Desktop/ebooks"   # Path to directory containing epub packages
  path_to_new_files = "/Users/username_5/Desktop/ebooks_conv"   # Path to store new epub files in
  
  # Function to store all filenames in a list
  def extract_filename(path_to_files):
      filenames = []
      for f in os.listdir(path_to_files):
          f_name, f_ext = os.path.splitext(f)
          if f_ext == ".epub":
              filenames.append(f_name)
      filenames.sort()
      return filenames
  
  # Function to generate new epub files
  def create_epub(filenames, path_to_files, path_to_new_files):
      total_files = len(filenames)
      for i, filename in enumerate(filenames, 1):
          epub_path = os.path.join(path_to_files, filename + ".epub")
          
          # Remove iTunesMetadata.plist if exists
          plist_path = os.path.join(path_to_files, "iTunesMetadata.plist")
          if os.path.exists(plist_path):
              os.remove(plist_path)
          
          # Copy the EPUB files to a temporary directory to avoid zipping recursively
          temp_dir = os.path.join(path_to_new_files, filename)
          shutil.copytree(epub_path, temp_dir)
          
          # Create the new EPUB archive
          with zipfile.ZipFile(os.path.join(path_to_new_files, filename + ".epub"), 'w') as new_epub:
              for root, dirs, files in os.walk(temp_dir):
                  for file in files:
                      file_path = os.path.join(root, file)
                      # Write each file to the archive
                      new_epub.write(file_path, os.path.relpath(file_path, temp_dir))
          
          # Clean up the temporary directory
          shutil.rmtree(temp_dir)
          
          print("File #", i, " has been processed successfully. Remaining files:", total_files - i)
  
  filenames = extract_filename(path_to_files)
  create_epub(filenames, path_to_files, path_to_new_files)
  
  ```
  
  
  ---
  
  