108

I am trying to create a graphical program for my script.

Inside the script I use tar to create a tar archive.

From the graphical program I get the full name of file that I want to create a tar archive.

tar -cvf temp.tar /home/username/dir1/dir2/selecteddir 

My tar archive includes home, username, dir1, dir2 and selecteddir while i want tar to create archive only including selecteddir.

7 Answers 7

146

You can use the -C option of tar to accomplish this:

tar -C /home/username/dir1/dir2 -cvf temp.tar selecteddir

From the man page of tar:

-C directory
         In c and r mode, this changes the directory before adding the following files.  
         In x mode, change directories after opening the archive but before extracting 
         entries from the archive.
9
  • do you know how i can split $path into selecteddir and path upto /home/username/dir1/dir2 so I can user -C option Nov 17, 2014 at 3:35
  • 2
    Worth adding that this is valid for both GNU and BSD Tar.
    – Luke Exton
    Jul 5, 2016 at 23:11
  • 14
    Note that you can't use globbing with the -C option. tar -C /home/username/dir1/dir2 -cvf temp.tar '*.csv' won't work. Aug 29, 2016 at 14:59
  • 4
    Doesn't work: tar: selecteddir: Cannot stat: No such file or directory
    – tribbloid
    Mar 25, 2018 at 2:59
  • 1
    @grenix but now you have ./ prefixing all files! See @mpen's answer
    – Hashbrown
    Jan 21, 2022 at 10:28
25

There are two methods that you can use to approach this problem.

The first one, in my opinion, is easier. Simply cd into directory directly above the one you want to compress. In this case it would be dir2.

$ cd /home/username/dir1/dir2/
$ tar -cvf temp.tar selecteddir

The second way is to use the option --transform which takes a sed expression and runs it against the files names. Note: you will have to escape / in the sed expression.

$ tar -cvf temp.tar /home/username/dir1/dir2/selecteddir --transform='s/\/home\/username\/dir1\/dir2\///g'
3
  • Does the first method need a dot (.) on the end? I tried it without and got: tar: Cowardly refusing to create an empty archive. When I have the dot, it annoyingly makes the root contain a directory named .. So, close but not perfect.
    – JW01
    Dec 21, 2015 at 12:58
  • 1
    Further to my previous comment. I solved my issue. $ cd /home/username/dir1/dir2/ && tar -cvf temp.tar selecteddir * worked for me. Using asterisk instead of a dot .. Update: Woops - Although I lost the hidden files.
    – JW01
    Dec 21, 2015 at 13:10
  • 3
    I know it's an old post but just in case: using a different delimiter may be easier than escaping, e.g. --transform='s:/home/username/dir1/dir2/::g'
    – David Z
    Jul 27, 2020 at 6:14
18

First, go to the working directory,

cd /your/working/directory/ 

Then use magic * :-)

tar -cvf temp.tar *
2
  • I'm trying to archive hidden directories and if I add them directly (No *) it works, but when using * it only adds the name of the archive to the archive ...
    – Ole
    Oct 5, 2018 at 10:35
  • 1
    You can use * and .* to get both regular and hidden files. You can also use --exclude thearchive.tar to avoid archiving some files
    – Kiruahxh
    Feb 12, 2020 at 14:03
11

Actually, I found a problem using Ketan's answer

tar -C /home/username/dir1/dir2 -cvf temp.tar selecteddir

When you want to just copy all files just in dir2, just all files then I first come out the idea:

tar -C /home/username/dir1/dir2 -cvf temp.tar *

However, when you are not in dir2 directory, it would cause problem since * would tar files in your current diectroy. And I fixed the problem using command below:

 tar -C /home/username/dir1/dir2 -cvf temp.tar ./
1
  • 22
    But then your temp.tar archive contains . as a root folder.
    – cgrim
    Oct 2, 2018 at 8:46
8

To avoid that dot dir, you can strip it after the fact:

tar czC /path/to/dir . --transform='s,^\./,,' >| foo.tgz

This will create an archive with only the contents of /path/to/dir.

6
  • This is a cool feature! Jan 17, 2022 at 20:10
  • Thanks, But how to remove the 0 byte . folder beside other files in the archive? This method still keeps that . folder inside archive. Jan 24, 2022 at 11:16
  • @DummyBeginner I don't know, (cd /foo && tar czvf /bar/archive.tar.gz * .*) seems to be the best solution.
    – mpen
    Jan 25, 2022 at 5:05
  • @mpen Yes, I think so., Although the .* at the end of cd /foo && tar czvf /bar/archive.tar.gz * .* is apparently redundant. Jan 25, 2022 at 6:25
  • 1
    @DummyBeginner Depends on your bash flags, whether or not you have the dotglob flag set I think it is
    – mpen
    Jan 25, 2022 at 7:10
1

The traditional and portable way to do it is with:

(cd /home/username/dir1/dir2 && tar cf - selecteddir | gzip) > temp.tar.gz

(or lzop/lz4/xz your preferred compressor; or you could skip compression altogether if you didn't care about saving space).

To uncompress into that same directory, you just reverse the pipeline:

(cd /home/username/dir1/dir2 && gzip -d | tar xpf -) < temp.tar.gz
0

If you want to tar a bunch of files without any parent folder, you can cd into the folder and then tar . (indicating the current directory) while specifying ../yourfiles.tar as the output file. For example, if you want to tar all the files in the yourfiles folder, then cd to the parent folder of yourfiles and type run this:

cd yourfiles && tar -cf ../yourfiles.tar . && cd ../

The parent of yourfiles will now also contain yourfiles.tar.

Note that when you extract yourfiles.tar with tar -xf yourfiles.tar it will extract all the files into the current directory, rather than creating a folder. However, if you right-click and "Extract here" in Ubuntu, it will create a folder called yourfiles to put the files in ("incorrect" behavior, but better UX).

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .