1

Using 7z, I'd like to print the names of the files inside an archive.

The output of 7z l myArchive.7z is

7-Zip [64] 16.02 : Copyright (c) 1999-2016 Igor Pavlov : 2016-05-21
p7zip Version 16.02 (locale=en_US.utf8,Utf16=on,HugeFiles=on,64 bits,4 CPUs Intel(R) Core(TM) i5-2520M CPU @ 2.50GHz (206A7),ASM,AES-NI)

Scanning the drive for archives:
1 file, 171329 bytes (168 KiB)

Listing archive: myArchive.7z

--
Path = myArchive.7z
Type = 7z
Physical Size = 171329
Headers Size = 237
Method = LZMA2:18
Solid = +
Blocks = 1

  Date      Time    Attr         Size   Compressed  Name
------------------- ----- ------------ ------------  ------------------------
2020-06-05 16:03:29 ....A            0            0  file with spaces
2020-06-05 11:53:13 ....A        96616       171092  screen_2020-06-05_11-53-13.png
2020-06-05 11:53:43 ....A       106932               screen_2020-06-05_11-53-43.png
------------------- ----- ------------ ------------  ------------------------
2020-06-05 16:03:29             203548       171092  3 files

I'd like to make 7z print only the file names:

file with spaces
screen_2020-06-05_11-53-13.png
screen_2020-06-05_11-53-43.png

Is there a way to do that?

2

Just use libarchive's bsdtar:

bsdtar tf file.7z

Also note that 7z l would prompt you for a password if the archive is encrypted while bsdtar will just return with an error which would be preferable in scripts.

| improve this answer | |
1

With -slt

This command

7z -slt l myArchive.7z | grep -oP "(?<=Path = ).+" | tail -n +2

prints

file with spaces
screen_2020-06-05_11-53-13.png
screen_2020-06-05_11-53-43.png

The -slt option "[s]ets technical mode for l (list) command", according to the manual.

This option makes 7z print information about the files of the archive in a parsable way.

Here's the output of 7z -slt l myArchive.7z:

Listing archive: file with spaces.7z

--
Path = file with spaces.7z
Type = 7z
Physical Size = 171329
Headers Size = 237
Method = LZMA2:18
Solid = +
Blocks = 1

----------
Path = file with spaces
Size = 0
Packed Size = 0
Modified = 2020-06-05 16:03:29
Attributes = A_ -rw-r--r--
CRC = 
Encrypted = -
Method = 
Block = 

Path = screen_2020-06-05_11-53-13.png
Size = 96616
Packed Size = 171092
Modified = 2020-06-05 11:53:13
Attributes = A_ -rw-r--r--
CRC = 41911DBA
Encrypted = -
Method = LZMA2:18
Block = 0

Path = screen_2020-06-05_11-53-43.png
Size = 106932
Packed Size = 
Modified = 2020-06-05 11:53:43
Attributes = A_ -rw-r--r--
CRC = B0ECEA85
Encrypted = -
Method = LZMA2:18
Block = 0

The grep part of the command | grep -oP "(?<=^Path = ).+" warrants explanation:

  • -o: grep only prints the matched string, not the whole line.
  • P: enable Perl compatible regular expressions in grep. We need this for the lookbehind in the regex.
  • (?<=^Path = ).+": grep's regex. Get all characters after the line starting with "Path = ". The (?<= part is a positive lookbehind which means the line has to start with "Path = ", but that string is not part of the match. The characters that come after are the matched string. Those characters are the file name.

After that, we have the archive name on the first line and all the file names below. We remove the first line with | tail -n +2.

| improve this answer | |
  • +1 just because I am always amazed at what can be done with perl, but wouldn't 7z -slt l myArchive.7z | sed 's/Path = \(.*\)/\1/' be more simple ? Just saying... – Cbhihe Jun 5 at 17:53
  • 1
    Thanks @Cbhihe. I modified your command to only print the file names: 7z -slt l myArchive.7z | sed -n 's/Path = \(.*\)/\1/p' | tail -n +2 – Matthias Braun Jun 5 at 18:46

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.