80

I wonder how to list the content of a tar file only down to some level?

I understand tar tvf mytar.tar will list all files, but sometimes I would like to only see directories down to some level.

Similarly, for the command ls, how do I control the level of subdirectories that will be displayed? By default, it will only show the direct subdirectories, but not go further.

ire_and_curses
  • 68,372
  • 23
  • 116
  • 141
Tim
  • 1
  • 141
  • 372
  • 590

6 Answers6

186

depth=1

tar --exclude="*/*" -tf file.tar


depth=2

tar --exclude="*/*/*" -tf file.tar
sacapeao
  • 1,961
  • 2
  • 11
  • 4
  • 6
    But this can get only file name, not folder name – VicX Nov 17 '16 at 08:07
  • 2
    This answer is dope. – th3pirat3 Feb 03 '17 at 16:45
  • I used the depth=1 solution and got two different results on archives that were made by specifying the current directory as the target. On one I got no out put at all. The other gave the output `./` . I don't know why they were different. – crantok Dec 07 '20 at 10:01
  • 2
    I think this only works on GNU tar. On BSD tar (included in macOS) it only lists top level files and not directories. I think it has something to do with `*` being interpreted as 0 or more character and ends up excluding any entry with a `/`. To include files and directories, I was able to use the pattern `"*/?*"`, and for depth=2, `"*/?*/?*"` would work. – Ryan C Jan 18 '22 at 03:04
40
tar tvf scripts.tar | awk -F/ '{if (NF<4) print }'


drwx------ glens/glens       0 2010-03-17 10:44 scripts/
-rwxr--r-- glens/www-data 1051 2009-07-27 10:42 scripts/my2cnf.pl
-rwxr--r-- glens/www-data  359 2009-08-14 00:01 scripts/pastebin.sh
-rwxr--r-- glens/www-data  566 2009-07-27 10:42 scripts/critic.pl
-rwxr-xr-x glens/glens     981 2009-12-16 09:39 scripts/wiki_sys.pl
-rwxr-xr-x glens/glens    3072 2009-07-28 10:25 scripts/blacklist_update.pl
-rwxr--r-- glens/www-data 18418 2009-07-27 10:42 scripts/sysinfo.pl

Make sure to note, that the number is 3+ however many levels you want, because of the / in the username/group. If you just do

tar tf scripts.tar | awk -F/ '{if (NF<3) print }'

scripts/
scripts/my2cnf.pl
scripts/pastebin.sh
scripts/critic.pl
scripts/wiki_sys.pl
scripts/blacklist_update.pl
scripts/sysinfo.pl

it's only two more.

You could probably pipe the output of ls -R to this awk script, and have the same effect.

Glen Solsberry
  • 11,960
  • 15
  • 69
  • 94
  • 3
    This is a brilliant answer. But I think you can simplify it a bit, since "print" is awk's default action: `tar tvf scripts.tar | awk -F/ 'NF<4'` – user98761 Jul 15 '21 at 01:11
10

Another option is archivemount. You mount it, and cd into it. Then you can do anything with it just as with other filesystem.

$ archivemount /path/to/files.tgz /path/to/mnt/folder

It seems faster than the tar method.

Community
  • 1
  • 1
Sisyphus
  • 896
  • 11
  • 19
6

It would be nice if we could tell the find command to look inside a tar file, but I doubt that is possible.

I quick and ugly (and not foolproof) way would be to limit the number of directory separators, for example:

 $ tar tvf myfile.tar | grep -E '^[^/]*(/[^/]*){1,2}$'

The 2 tells to display not more than 2 slashes (in my case one is already generated by the user/group separator), and hence, to display files at depth at most one. You might want to try with different numbers in place of the 2.

leonbloy
  • 73,180
  • 20
  • 142
  • 190
5

I agree with leonbloy's answer - there's no way to do this straightforwardly within the tarball itself.

Regarding the second part of your question, ls does not have a max depth option. You can recurse everything with ls -R, but that's often not very useful.

However you can do this with both find and tree. For example to list files and directories one level deep, you can do

find -maxdepth 2

or

tree -L 2

tree also has a -d option, which recursively lists directories, but not files, which I find much more useful than -L, in general.

Community
  • 1
  • 1
ire_and_curses
  • 68,372
  • 23
  • 116
  • 141
  • True. And you can add the "-ls" option to the "find" command, if you want an output similar to that of the "tar tvf" – leonbloy Apr 23 '10 at 18:17
1

I was able to show only the directory names at a particular depth using grep:

for depth 3:

tar -tf mytar.tar | grep -Ex '([^/]+/){3}'

or for depth $DEPTH:

tar -tf mytar.tar | grep -Ex '([^/]+){$DEPTH}/'

You can speed that up by combining grep with --exclude from @sacapeao's accepted answer.

for depth 3:

tar --exclude '*/*/*/*/*' -tf mytar.tar | grep -Ex '([^/]+/){3}'
hobs
  • 18,473
  • 10
  • 83
  • 106