untar tar file using --strip-components=1 - linux

I have a tar file which has multiple folders like this:
code.tar
bin/
startup.sh
WebServer/
appname
webappname
Configuration/
a.properties
b.properties
If I unzip code.tar, I get a folder name code with all the folder structure under it, but I want to extract the contents of code.tar and just get the sub-folder structure under it (ie bin/, WebServer/, configuration/ and files in these folders).
When I use tar -xzf code.tar -C <path> --strip-components=1 I get all the contents of subfolders ie startup.sh,appname etc along with the sub-folders-
eg on running above command I get all these folders and files at same level-
bin/
startup.sh
WebServer/
appname
webappname
Configuration/
a.properties
b.properties
please help

Your command seems right.
Suppose you have folder "extract" you want to extract the file to:
tar -xzf code.tar -C extract --strip-components=1
So this will truncate the upper folder "code" and just extract the contents with the file-folder structure preserved.

There's no explicit flag to allow tar to only extract the files at that depth and not the files any deeper (which is what I'm interpreting the question to mean); Generally you would need to explicitly specify what's to be extracted; e.g.
tarfile="foo.tar.xz"
tar -xf "$tarfile" --strip-components=1 $(tar tf $tarfile | awk -F/ '{if (NF <= 2 && $NF != "") print; }')
We use the list of entries from tar (tar tf) and filter through awk, where when we find any entries with <= 2 items, and that isn't a directory ($NF != "") then we print them.
This will give you all the files that need to be extracted from the archive, which is then passed to an explicit extraction command.

Related

Zip and Tar compress entire top directory and not (sub)directory

I'm trying to only zip the directory where I am exactly, this is part of a bigger bash script so I need to cd into the directory where I want to extract files and then exit.
However, using either tar or zip, the entire top directory path is recreated and not just the subdirectory that I'm interested in.
I get the following error:
zip warning: name not matched: $PWD/*
What I'm trying to do:
#Sub Directory and contents will be compressed
cd "$Sub_Dir"
Zipped_Files=$(basename "$Sub_Dir")
zip -r "$Zipped_Files".zip "$PWD/*"
#or
zip -j "$Zipped_Files".zip "$PWD/*"
#or
#tar -zcf "$Zipped_Files".zip "$PWD"
echo "Files have been compressed"
You have already cd into the sub dir, zip -r "$Zipped_Files".zip ./* should work.

Using 'tar' command in for loop

I know it is the basic question but please do help me .I compressed and archived my server log file using tar command
for i in server.log.2016-07-05 server.log.2016-07-06 ; do tar -zcvf server2.tar.gz $i; done
The output of the above loop is:
server.log.2016-07-05
server.log.2016-07-06
But while listing the file using tar -tvf server2.tar.gz the output obtained is:
rw-r--r-- root/root 663643914 2016-07-06 23:59 server.log.2016-07-06
i.e., I archived two files but only one file was displayed which means archive doesnt have both files right?? Please help on this.
I just tested with these two files but my folder has multiple files. Since I didn't get expected output I was not proceeded with all the files in my folder. The exact loop I am going to use is:
Previousmonth=$(date "+%b" --date '1 month ago')
for i in $(ls -l | awk '/'$Previousmonth'/ && /server.log./ {print $NF}');do;tar -zcvf server2.tar.gz $i;done
I am trying to compress and archive multiple files but while listing the files using tar -tvf it doesn't shows all the files.
You don't need a loop here. Just list all the files you want to add as command line parameter:
tar -zcvf server2.tar.gz server.log.2016-07-05 server.log.2016-07-06
The same goes for your other example too:
tar -zcvf server2.tar.gz $(ls -l | awk '/'$Previousmonth'/ && /server.log./ {print $NF}')
Except that parsing the output of ls -l is awful and strongly not recommended.
But since the filenames to backup contain the month number,
a much simpler and better solution is to get the year + month number using the date command, and then use shell globbing:
prefix=$(date +%Y-%m -d 'last month')
tar -zcvf server2.tar.gz server.log.$prefix-??

how to rename files you put into a tar archive using linux 'tar'

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

Tarring files exclude the path before the folder i want to tar

Im trying to tar a set of subfolders and then tar its parent folder afterwards via a ruby script.
The structure is as follows:
/x/y/z/ParentFolder/Subfolder1
/x/y/z/ParentFolder/Subfolder2
/x/y/z/ParentFolder/Subfolder3
/x/y/z/ParentFolder/Subfolder4
So what i want to end up with is Subfolder1.tar.gz,Subfolder2.tar.gz,Subfolder3.tar.gz,Subfolder4.tar.gz all contained in ParentFolder.tar.gz.
My problem at the moment is that im able to tar the parent folder with its subfolders but it structure remains as /x/y/z/ParentFolder/SubFolder1----4
tarParentFolder = "tar -zcvf /x/y/z/ParentFolder.tar.gz /x/y/z/ParentFolder 2>/dev/null"
`#{tarParentFolder}`
I have searched around but cannot seem to find a solution to this,
Anybody got any ideas?
Thanks
The answer to how to get the path to be relative to the right path is to use the -C tar option. That's a capital C. The parameter you pass is the directory from which you want the tar to start relative.
so you would do:
tar -zcvf /x/y/z/ParentFolder.tar.gz -C /x/y/z ParentFolder
But ... you should also probably think twice about putting tars in tars. You should be fine just tarring up the containing dir.
For creating tar archives containing multiple files/folders use this:
$ mkdir f1 f2
$ tar -czf tar.tgz f1 f2 # creates the tar
$ tar -tzf tar.tgz # lists tar contents
f1/
f2/
f3/
$
So you should write something like:
tar -zcvf /x/y/z/ParentFolder.tar.gz /x/y/z/Subfolder{1,2,3,4}

How do I tar a directory without retaining the directory structure?

I'm working on a backup script and want to tar up a file directory:
tar czf ~/backup.tgz /home/username/drupal/sites/default/files
This tars it up, but when I untar the resulting file, it includes the full file structure: the files are in home/username/drupal/sites/default/files.
Is there a way to exclude the parent directories, so that the resulting tar just knows about the last directory (files)?
Use the --directory option:
tar czf ~/backup.tgz --directory=/home/username/drupal/sites/default files
Hi I've a better solution when enter in the specified directory it's impossible (Makefiles,etc)
tar -cjvf files.tar.bz2 -C directory/contents/to/be/compressed .
Do not forget the dot (.) at the end !!
cd /home/username/drupal/sites/default/files
tar czf ~/backup.tgz *
Create a tar archive
tar czf $sourcedir/$backup_dir.tar --directory=$sourcedir WEB-INF en
Un-tar files on a local machine
tar -xvf $deploydir/med365/$backup_dir.tar -C $deploydir/med365/
Upload to a server
scp -r -i $privatekey $sourcedir/$backup_dir.tar $server:$deploydir/med365/
echo "File uploaded.. deployment folders"
Un-tar on server
ssh -i $privatekey $server tar -xvf $deploydir/med365/$backup_dir.tar -C $deploydir/med365/
To gunzip all txt (*.txt) files from /home/myuser/workspace/zip_from/
to /home/myuser/workspace/zip_to/ without directory structure of source files use following command:
tar -P -cvzf /home/myuser/workspace/zip_to/mydoc.tar.gz --directory="/home/myuser/workspace/zip_from/" *.txt
If you want to tar files while keeping the structure but ignore it partially or completely when extracting, use the --strip-components argument when extracting.
In this case, where the full path is /home/username/drupal/sites/default/files, the following command would extract the tar.gz content without the full parent directory structure, keeping only the last directory of the path (e.g. files/file1).
tar -xzv --strip-components=5 -f backup.tgz
I've found this tip on https://www.baeldung.com/linux/tar-archive-without-directory-structure#5-using-the---strip-components-option.
To build on nbt's and MaikoID's solutions:
tar -czf destination.tar.gz -C source/directory $(ls source/directory)
This solution:
Includes all files and folders in the directory
Does not include any of the directory structure (or .) in the final product
Does not require you to change directories.
However, it requires the directory to be given twice, so it may be most useful in another script. It may also be less efficient if there are a lot of files/folders in source/directory. Adjust the subcommand as necessary.
So for instance for the following structure:
|- source
| |- one
| `- two
`- working
the following command:
working$ tar -czf destination.tar.gz -C ../source $(ls ../source)
will produce destination.tar.gz where both one and two (and sub-files/-folders) are the first items.
This worked for me:
gzip -dc "<your_file>.tgz" | tar x -C <location>
For me -C or --directory did not work, I use this
cd source/directory/or/file
tar -cvzf destination/packaged-app.tgz *.jar
# this will put your current directory to what it previously was
cd -
Kindly use the below command to generate tar file without directory structure
tar -C <directoryPath> -cvzf <Path of the tar.gz file> filename1 filename2... filename N
eg:
tar -C /home/project/files -cvzf /home/project/files/test.tar.gz text1.txt text2.txt
tar -Cczf ~/backup.tgz /home/username/drupal/sites/default/files
-C does the cd for you

Resources