112

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 Answers7

151

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.
Ketan
  • 9,226
  • do you know how i can split $path into selecteddir and path upto /home/username/dir1/dir2 so I can user -C option – Sujit Maharjan Nov 17 '14 at 03:35
  • @SujitMaharjan you can use dirname to extract everything until "selecteddir" and basename to extract "selecteddir". Try the two commands with the $path as argument. – Ketan Nov 17 '14 at 03:42
  • 2
    Worth adding that this is valid for both GNU and BSD Tar. – Luke Exton Jul 05 '16 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. – Christian Long Aug 29 '16 at 14:59
  • 4
    Doesn't work: tar: selecteddir: Cannot stat: No such file or directory – tribbloid Mar 25 '18 at 02:59
  • Special use case tar -C /home/username/dir1/dir2/selecteddir -cvf temp.tar . to only reflect the tree of selecteddir witout 'selcteddir/' preceding every filename. – grenix Dec 22 '21 at 11:53
  • 1
    @grenix but now you have ./ prefixing all files! See @mpen's answer – Hashbrown Jan 21 '22 at 10:28
  • thats true, but for further processing the preceding './' does not harm for many cases. Even if you assume another base direcory '/base/./path_to_file' is effectively the same than '/base/path_to_file'. Furthermore it ressembles the output format of 'find . -type f' which might be of advatage for some use cases. – grenix Jan 24 '22 at 10:34
  • Reason, why you can't use globbing with Asterisk *: https://unix.stackexchange.com/a/71464/408419 – User Rebo Jun 08 '23 at 06:29
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'
  • 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 '15 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 '15 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 '20 at 06:14
20

First, go to the working directory,

cd /your/working/directory/ 

Then use magic * :-)

tar -cvf temp.tar *
Yas
  • 329
  • 2
  • 3
  • 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 05 '18 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 '20 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 ./
Guan YANG
  • 119
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.

mpen
  • 913
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).

joe
  • 172
  • 7