开发者

Output the root directory in a tar archive

I'm trying to automate the process you go through when compiling something like nginx using a shell script. (I don't want to use apt-get)

Currently I have this:

wge开发者_如何学Got http://nginx.org/download/nginx-1.0.0.tar.gz
tar xf nginx-1.0.0.tar.gz

But next I need to find out what the directory name is from where it extracted too so I can start the configure script.


Use this to find out the top-level directory(-ies) of an archive.

tar tzf nginx-1.0.0.tar.gz | sed -e 's@/.*@@' | uniq

sed is invoked here to get the first component of a path printed by tar, so it transforms

path/to/file --> path

It does this by executing s command. I use @ sign as a delimiter instead of more common / sign to avoid escaping / in the regexp. So, this command means: replace part of string that matches /.* pattern (i.e. slash followed by any number of arbitrary characters) with the empty string. Or, in other words, remove the part of the string after (and including) the first slash.

(It has to be modified to work with absolute file names; however, those are pretty rare in tar files. But make sure that this theoretical possibility does not create a vulnerability in your code!)


Using sed as described in the other answer is a good approach, but it's better to use head -1 before sed instead of uniq after; this has much better performance - you are pumping only the first line through sed and this also avoids the requirement of uniq to load the entire output of sed into memory. Furthermore, if the tar contains multiple top level directories, this will return the first top level directory, whereas uniq will give you all top level directories.

tar tzf nginx-1.0.0.tar.gz | head -1 | sed -e 's/\/.*//'

I personally find it more readable to escape the internal / in the pattern match of sed as \/ rather than introducing another delimiter such as @, but that's just a matter of preference


How about this one for getting all top level directories (including . ):

tar tf nginx-1.0.0.tar.gz | xargs dirname | sort | uniq

To get the first top level directory I would use the solution posted by @thomas-steinbach:

tar tf nginx-1.0.0.tar.gz | head -1


This command only uses tar:

tar --exclude=\*/\*/\* --no-wildcards-match-slash -tzf nginx-1.0.0.tar.gz

The funny exclude pattern, unescaped, is */*/* and means "exclude all files and directories that are two levels deep": the first * is for the base directory, the second is for the files and directories at first level, the third is for the files and directories at second level.

This could only work if the wildcards match just the file/directory names, without the slashes. That's why --no-wildcards-match-slash is there.


The directory name should be nginx-1.0.0 or whatever the tarball's name is without the .tar.gz. Try this after wget and tar:

cd nginx*
./configure
# etc

You could also use variables, if you like.

name='nginx-1.0.0' # or $1, or whatever works for you
wget "http://nginx.org/download/$name.tar.gz"
tar -xf "$name.tar.gz"
./$name/configure

Honestly, though, the best solution would be to cd into the proper directory after extracting, whether you use a glob or a variable for the directory name.


The answers given here doesn't work well for absolute paths as they prune them to the first directory of the path. If you have created a tar archive with absolute paths, the following snippet would return its originally root:

tar tf archive.tar | head -1

For compresseed .tar.gz archives add the option c. Hope this would help some others.


Many of the above answers are correct, but I encounter a situation where the actual tar stopped as a result of piping to head.

The following command in Borne shell:

tar -v -zxf plotutils-3.1.tar.gz | head -1 | cut -d "/" -f 1

Will produce the top directory name: plotutils-3.1 However, the resulting directory will be either empty or containing one item. I am using ubuntu. To get the actual result of the tar you have to do another command

tar -zxf plotutils-3.1.tar.gz  

again. I am not sure I am doing something wrong here; but this should be noted. I found this out when trying to write a shell script to automatically run the autotool's configure script. Hope this may help others.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜