指定したサブディレクトリにtar.gzファイルを抽出するスクリプトがありますmysubfolder:
mkdir mysubfolder; tar --extract --file=sourcefile.tar.gz --strip-components=1 --directory=mysubfolder;
Zipファイルでこれを行う同等の方法はありますか?
Mathiasが言ったように、unzip
にはそのようなオプションはありませんが、1行のbashスクリプトで処理できます。
問題は、最善の方法はアーカイブのレイアウトに依存することです。 仮定単一のトップレベルディレクトリというソリューションは、コンテンツがアーカイブルートに直接ある場合、無残に失敗します(/a/foo
/b/foo
/foo
とカオスについて考えてください) /a
と/b
)を取り除きます。
そして、同じ失敗がtar --strip-component
でも起こります。万能のソリューションはありません。
したがって、ルートディレクトリを削除するには、is one(およびonly one)があると仮定します。
unzip -d "$dest" "$Zip" && f=("$dest"/*) && mv "$dest"/*/* "$dest" && rmdir "${f[@]}"
2番目のレベルのファイル/ディレクトリにnotが最上位の親と同じ名前(たとえば、/foo/foo
)を持っていることを確認してください。ただし、/foo/bar/foo
と/foo/bar/bar
は問題ありません。そうした場合、または単に安全にしたい場合は、一時ディレクトリを使用して抽出できます。
temp=$(mktemp -d) && unzip -d "$temp" "$Zip" && mkdir -p "$dest" &&
mv "$temp"/*/* "$dest" && rmdir "$temp"/* "$temp"
Bashを使用している場合は、トップレベルが単一のディレクトリであるかどうかをテストできます。
f=("$temp"/*); (( ${#f[@]} == 1 )) && [[ -d "${f[0]}" ]] && echo "Single dir!"
Bashといえば、dotglob
をオンにして隠しファイルを含める必要があります。また、すべてを単一の便利な関数でラップできます。
unzip-strip() (
local Zip=$1
local dest=${2:-.}
local temp=$(mktemp -d) && unzip -d "$temp" "$Zip" && mkdir -p "$dest" &&
shopt -s dotglob && local f=("$temp"/*) &&
if (( ${#f[@]} == 1 )) && [[ -d "${f[0]}" ]] ; then
mv "$temp"/*/* "$dest"
else
mv "$temp"/* "$dest"
fi && rmdir "$temp"/* "$temp"
)
それを~/.bashrc
または~/.profile
に入れてください。もう心配する必要はありません。単に次のように使用します:
unzip-strip sourcefile.Zip mysubfolder
(存在しない場合は、自動的にmysubfolder
が作成されます)
unzip
のマニュアルページ にそのようなオプションが見つからなかったので、これは不可能だと思います。 :(
ただし、(状況によっては)回避できます。たとえば、Zipファイルの最上位ディレクトリがfoo-
に続いてバージョン番号を付けると、次のようになります。
cd /tmp
unzip /path/to/file.Zip
cd foo-*
cp -r . /path/to/destination/folder
-j
を使用してパスをジャンク化できます(ディレクトリを作成しないでください)。これは、ある程度一般的な単一レベルのアーカイブにのみ推奨されます。マルチレベルのディレクトリ構造を持つアーカイブはフラット化されます-これにより、抽出するファイルの名前が衝突する可能性さえあります。
Unzipのmanページから:
-j junk paths. The archive's directory structure is not recreated; all files are deposited in the extraction directory (by default, the current one).