2

I can extract a specific file from a tar archive like this:

tar xvf gh_2.5.1_linux_armv6.tar.gz gh_2.5.1_linux_armv6/bin/gh

This extracts to the current directory, but the gh file is still within the directory structure in the archive. Is there a way to have the file extract into the current or any given directory instead?

paradroid
  • 1,159
  • 1
  • 13
  • 28
  • 1
    If your system uses GNU tar, this may help [What does --strip-components -C mean in tar?](https://unix.stackexchange.com/questions/535772/what-does-strip-components-c-mean-in-tar) – steeldriver Feb 15 '22 at 23:07

3 Answers3

2

For gnu tar, try

tar xvf gh_2.5.1_linux_armv6.tar.gz --one-top-level=. gh_2.5.1_linux_armv6/bin/gh

or, as suggested in comments, instead of --one-top-level, use --strip-components=2 for this example, but that might not work if you want to extract multiple files from different directories.

user10489
  • 5,834
  • 1
  • 10
  • 22
  • That made no difference and the file was still extracted to within the directory structure. `--strip-components` worked though.⎄n – paradroid Feb 16 '22 at 00:18
1

Answer using GNU tar:

tar xvf gh_2.5.1_linux_armv6.tar.gz gh_2.5.1_linux_armv6/bin/gh -O > gh

You can try the code block above. O option is making output stdout. So you combine with redirection operator.

sakkke
  • 183
  • 6
  • This works, but be aware that file permissions for executables are lost and change to umask default. `--strip-components` is probably best for single files. – paradroid Feb 17 '22 at 12:24
1

As suggested in comments, for a single file or for multiple files located on the same level in the archive, the option --strip-components=N, works fine.
The other GNU tar option that works for any number of files located anywhere in the archive is --xform (or --transform).
It allows modifying file names using a sed-like replace expression of the form:

s/regexp/replace/[flags]

so in your case the expression s|.*/|| removes all leading components from the file path i.e.

tar xvf gh_2.5.1_linux_armv6.tar.gz  --xform='s|.*/||' gh_2.5.1_linux_armv6/bin/gh

extracts only the gh file (without any parent directories) in the current directory. Also, one can see the requested transformations applied with the --show-transformed-names option e.g. dry run:

tar -tf archive.tar.gz --xform='s|.*/||' --show-transformed-names

This can be combined with other options, e.g. extract based on pattern, to another directory:

tar -xvzf archive.tar.gz --xform='s|.*/||' -C dest_dir --wildcards --no-anchored 'match*'
don_crissti
  • 79,330
  • 30
  • 216
  • 245