私のWindowsコンピュータで(私は制御できません).zipを作成しました。 zipファイルには、解凍時に保存する必要があるパスが含まれています。
ただし、解凍すると、すべてのファイルが次のように終了します。
unzip_dir/\window\path\separator\myfile.ext
オプションがあるものとないものすべて試してみました-j
。私の問題は私です必要以下のパス情報です\window\path\separator\
。解凍時にこのファイル構造を作成する必要があります。
スクリプトからファイルを簡単に作成しmv
て反転できます\
が、/
ターゲットパスディレクトリが存在しないというエラーが発生します。現在の回避策は、mkdir -p
パス(変換\
後/
)を選択し、ファイルcp
をそのパスに転送することです。
ただし、ファイルが多すぎるため、mkdir -p
これらのファイルごとに重複したステートメントが原因で作業が遅くなる可能性があります。
Windowsパスを含むzipファイルをLinuxパスに変換するよりエレガントな方法はありますか?
答え1
7z rn
スラッシュを含むようにアーカイブのファイル名を変更するために使用されます。その後、アーカイブを抽出するとディレクトリが作成されます。
ファイル名を変更するには、スラッシュを含むアーカイブのファイルパスを一覧表示し、awk
バックスラッシュをスラッシュに変更するなどの代替文字列のリストを生成します。
7z rn windows.zip $(7z l windows.zip | grep '\\' | awk '{ print $6, gensub(/\\/, "/", "g", $6); }' | paste -s)
答え2
Windowsでzipファイルを作成するとき(移植可能な)スラッシュがあるため、zipファイルを作成するときに問題が発生したようです。
zip.exe -r pip pip
updating: pip/ (244 bytes security) (stored 0%)
adding: pip/pip.log (164 bytes security) (deflated 66%)
ただし、ファイル名にバックスラッシュがある「パス」を含むファイルがあるので、次のプログラムを実行できます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))
これは、プログラムの開始ディレクトリの下のすべてのディレクトリにあるファイルを処理します。説明する問題を考慮すると、起動するunzip_dir
サブディレクトリがなく、プログラムは現在のディレクトリ内のファイルに対してのみ繰り返すことができます。
答え3
これは、@madmuffinの修正(FileExistsError: [Errno 17] File exists
および不足しているos
モジュールのインポート)、Python 3の修正(SyntaxError: Missing parentheses in call to 'print'
)、および不足しているモジュールのインポートに対する修正errno
(NameError: name 'errno' is not defined
)を含む@antonの回答に対する更新のみです。
#! /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))
答え4
標準は、すべてのスラッシュがスラッシュでなければならないと述べています。
https://pkware.cachefly.net/webdocs/casestudies/APPNOTE.TXT
4.4.17.1 The name of the file, with optional relative path.
The path stored MUST NOT contain a drive or
device letter, or a leading slash. All slashes
MUST be forward slashes '/' as opposed to
backwards slashes '\' for compatibility with Amiga
and UNIX file systems etc. If input came from standard
input, there is no file name field.
以下は、問題のないzipファイルを修正し、以前の回答で欠落しているスペースも処理するスクリプトです。
#!/bin/sh
CMD_INSTRUCTIONS=$(7z l -ba -slt "$1" | grep '\\' | sed 's/^Path = //g' | sed 's/.*/"&"/' | gawk '{ print $0, gensub(/\\/, "/", "g", $0); }' | sed 's|\\|\\\\|g' | paste -s -)
CMD_7Z="7z rn \"$1\" $CMD_INSTRUCTIONS"
eval "$CMD_7Z"
源泉:
- @DozyBratの答えには元のスクリプトがありますが、ファイル名のスペースを処理しません。
- https://superuser.com/questions/1382839/zip-files-expand-with-backslashes-on-linux-no-subdirectories