سؤال

I'm trying to create a tar archive with a couple files, but rename those files in the archive. Right now I have something like this:

tar -czvf file1 /some/path/to/file2 file3 etc

But I'd like to do something like:

tar -czvf file1=file1 /some/path/to/file2=file2 file3=path/to/renamedFile3 etc=etc

Where, when extracted into directory testDir, you would see the files:

  • testDir/file1
  • testDir/file2
  • testDir/path/to/renamedFile3
  • testDir/etc

How can I do this?

هل كانت مفيدة؟

المحلول

You can modify filenames (among other things) with --transform. For example, to create a tape archive /tmp/foo.tar, putting files /etc/profile and /etc/bash.bashrc into it while also renaming profile to foo, you can do the following:

tar --transform='flags=r;s|bar|foo|' -cf file.tar file1 file2 bar fubar /dir/*

Results of the above is that bar is added to file.tar as foo.

The r flag means transformations are applied to regular files only. For more information see GNU tar documentation.

You can use --transform multiple times, for example:

tar --transform='flags=r;s|foo|bar|' --transform='flags=r;s|baz|woz|' -cf file.tar /some/dir/where/foo/is /some/dir/where/baz/is /other/stuff/* /dir/too

نصائح أخرى

With --transform, there's no need to make a temporary testDir first. To prepend testDir/ to everything in the archive, match the beginning anchor ^:

tar --transform "s|file3|path/to/renamedFile3|" \
    --transform "flags=r;s|^|testDir/|" \
    -czvf my_archive.tgz file1 /some/path/to/file2 file3 etc

The r flag is critical to keep the transform from breaking any symlink targets in the archive (which also match ^).

We can refer to the man tar, the -O option is the best choice since files can be written to standard out.

-O      (x, t modes only) In extract (-x) mode, files will be written to
         standard out rather than being extracted to disk.  In list (-t)
         mode, the file listing will be written to stderr rather than the
         usual stdout.

here are the examples:

# 1. without -O
tar xzf 20170511162930.db.tar.gz
# result: 20170511162930.db

# 2. with -O
tar xzf 20170511162930.db.tar.gz -O > latest.db
# result: latest.db

After not liking any solution that I've found, I've just written tarlogs.py, which lets you specify arbitrary names for tar entries. Each tar entry is constructed from one (or several) regular (or gzipped) inputs. You can also add directories, which will be recursed into as with regular tar. So in your case,

tarlogs.py -o file1 -i /some/path/to/file2 -o file2 -i file3 -o path/to/renamedFile3 -o /etc >output.tar

(-o with no -i inputs simply uses the output path as input, with no renaming)

This question has been up for a while, but for anyone who's looking for another suitable solution:
I've created a fork of the original GNU tar utility with additional support for file name mapping.

Usage example:

> touch myfile.txt
> tar cf file.tar ':myfile.txt:dir/inside/tar/newname.txt'
> tar tvf file.tar
  -rw-rw-r-- user/user      0  2022-02-12 14:27 dir/inside/tar/newname.txt

The feature is triggered by prefixing file names with a colon (:) as shown above. A second colon functions as a separator between the source file location and the desired file name inside the archive.

:[source file]:[desired name inside the tar]

This feature is compatible with the -T (input list from file) flag.

How to compile it

> git clone https://github.com/leso-kn/tar
> cd tar
> ./bootstrap
> ./configure
> make -j4
# Run it
> src/tar --version
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top