1

I have about 300 7zip archives, each with several files in them, and no directory structure inside.

I need to extract all these archives to folders that match the respective archive.

Example:

foo.7z
bar.7z

Extract contents of foo.7z to /foo/
Extract contents of bar.7z to /bar/


I tried this script:

find . -name "*.7z" -type f| xargs -I {} 7z x -o{} {}

But it resulted in:

can not open output file ./foo.7z/file.bin
Skipping    file.bin

What am I doing wrong? I'm using Ubuntu Linux.

  • @platinums Pretty hard to use context menus on a non-graphical operating system. – Moses Jul 23 '17 at 16:15
3

You're trying to create a directory with the same name as the file. That cannot work: There can't be two directory entries with the same name.

One way to fix this is to use basename to strip the .7z extension from the files and create the directories without the .7z suffix.

Like:

for archive in *.7z; do 7z x -o"`basename \"$archive\" .7z`" "$archive"; done
  • When I try that I get "there is no such archive". – Moses Nov 12 '15 at 15:15
  • Did you have any spaces in the archive names? I have fixed the command in the answer to properly handle filenames that contain whitespace. – Vojtech Nov 12 '15 at 18:21
  • Ah, yes that was it. Thanks! Worked beautifully. – Moses Nov 12 '15 at 18:55
1
for file in *.7z; do
    directory=${file/%.7z/}
    if mkdir ${directory}; then
        ( cd ${directory}; 7z x ../${file} )
    else
        echo "Unable to create directory ${directory} for archive ${file}" 1>&2
    fi
done

The way this works is first iterating through all the *.7z files using the file variable. Once it grabs a filename, it uses bash string manipulation to strip the .7z off the end, and make a new variable, directory, out of that.

It will then try to create the directory, and, if it can, it will open up a subshell, go into that directory, and extract the 7zip archive.

If it was not able to create that directory, a message is sent to standard error.

I use a subshell so as to not have to worry about losing track of where I am with changes to the working directory.

The most abstruse part of this is this line:

directory=${file/%.7z/}

This is the aforementioned bash string manipulation, which will look for .7z at the end of a string, and if present, replace it with nothing. If I wanted to replace it with, say, .zip, I could use ${file/%.7z/.zip}.

  • 2
    Can you expand your answer to explain what this code does, how to run it, and how it addresses the problem? Cautious readers are wary of unexplained code, and it's discouraged, because it doesn't teach the solution. Thanks. – fixer1234 Nov 12 '15 at 18:48
  • Thanks for the feedback, @fixer1234, I have expanded upon my answer as you have requested. – DopeGhoti Nov 12 '15 at 19:12

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.