tar展開時に不要な親ディレクトリを取り除きたい

GitHubのリリースアーカイブなど、tarアーカイブはmyproject-1.2.3/のような親ディレクトリを1つ持つ構成であることが多い。そのまま展開すると余分な階層ができてしまい、展開先のディレクトリ構成をそろえたい場合に扱いづらい。--strip-componentsオプションを使うと、展開時に先頭のパスから指定した階層数を取り除ける。

–strip-components オプションの基本

--strip-components=Nを指定すると、アーカイブ内の各ファイルのパスから先頭N階層を除去して展開する。

$ tar -xzf archive.tar.gz --strip-components=N

具体例

以下のような構造のmyproject-1.2.3.tar.gzがあるとする。

myproject-1.2.3/
├── src/
│   └── main.go
├── config/
│   └── app.yaml
└── README.md

展開する前に-tvfオプションでアーカイブの中身を確認すると、親ディレクトリの階層数が分かる。

$ tar -tvf myproject-1.2.3.tar.gz
drwxr-xr-x root/root         0 2026-07-10 21:26 myproject-1.2.3/
-rw-r--r-- root/root         7 2026-07-10 21:26 myproject-1.2.3/README.md
drwxr-xr-x root/root         0 2026-07-10 21:26 myproject-1.2.3/src/
-rw-r--r-- root/root         5 2026-07-10 21:26 myproject-1.2.3/src/main.go
drwxr-xr-x root/root         0 2026-07-10 21:26 myproject-1.2.3/config/
-rw-r--r-- root/root         7 2026-07-10 21:26 myproject-1.2.3/config/app.yaml

すべてのパスがmyproject-1.2.3/から始まっており、親ディレクトリは1階層であることが分かる。

-t--strip-componentsを付けても一覧表示のパスは変化しない。--strip-componentsは展開(-x)時のパス変換にのみ効き、一覧表示には反映されない仕様のため、-tで階層を取り除いた結果を事前にプレビューできない。

$ tar -tvf myproject-1.2.3.tar.gz --strip-components=1
drwxr-xr-x root/root         0 2026-07-10 21:26 myproject-1.2.3/
-rw-r--r-- root/root         7 2026-07-10 21:26 myproject-1.2.3/README.md
drwxr-xr-x root/root         0 2026-07-10 21:26 myproject-1.2.3/src/
-rw-r--r-- root/root         5 2026-07-10 21:26 myproject-1.2.3/src/main.go
drwxr-xr-x root/root         0 2026-07-10 21:26 myproject-1.2.3/config/
-rw-r--r-- root/root         7 2026-07-10 21:26 myproject-1.2.3/config/app.yaml

--strip-components=1を付けていない-tvfの結果と完全に同じ出力になる。この1階層を取り除いて展開するには--strip-components=1を指定する。

$ tar -xzf myproject-1.2.3.tar.gz -C extract --strip-components=1

extractディレクトリにはmyproject-1.2.3/を除いたREADME.mdsrc/main.goconfig/app.yamlが直接展開される。-Cオプションで展開先ディレクトリを指定しておくと、myproject-1.2.3という名前のディレクトリを事前に作る必要がない。

階層数がファイルのパス階層以上の場合の挙動

--strip-componentsに指定した数が、そのファイルのパスの階層数以上になる場合、そのファイルは展開されずスキップされる。

先ほどのmyproject-1.2.3.tar.gz--strip-components=2を指定して展開すると、一部のファイルがスキップされる。-vオプションを付けて展開すると、実際に処理されたファイルを確認できる。

$ tar -xzvf myproject-1.2.3.tar.gz -C extract2 --strip-components=2
myproject-1.2.3/src/main.go
myproject-1.2.3/config/app.yaml

出力にmyproject-1.2.3/README.mdが含まれていない。README.mdmyproject-1.2.3/README.mdという2階層のパスしか持たず、2階層すべてを取り除くとファイル名すら残らないため、展開されずスキップされる。src/main.goconfig/app.yamlは3階層のパスを持つため、2階層取り除いてもmain.goapp.yamlとして展開される。

-vで表示されるのはアーカイブ内の元のパスであり、実際に展開されるパスとは異なる点に注意する。アーカイブ内のファイルによって階層数は異なるため、意図しないファイルまでスキップされる場合がある。

GitHubのリリースアーカイブを展開する例

GitHubのリリースアーカイブはリポジトリ名-バージョン/という親ディレクトリを持つことが多く、--strip-components=1との組み合わせがよく使われる。

$ mkdir -p /usr/local/mytool
$ curl -L https://github.com/example/mytool/archive/refs/tags/v1.2.3.tar.gz \
    | tar -xz -C /usr/local/mytool --strip-components=1

パイプでtarに渡す場合も-C--strip-componentsを組み合わせることで、余分な親ディレクトリを作らずに任意の場所へ展開できる。

関連記事