0

Extract a tar file with content dir1/dir2/file, using --exclude dir2 switch. The gnu tar excluded but busybox's tar doesn't.

Use --exclude dir1/dir2 works fine, but why? Is there a way to exclude any directory named dir2 with busybox's tar?

The test.sh here:

# busybox 1.36 tested on debian:11 livecd and fedora:37 livecd
busybox

# clear old files
rm -rf bb-test

# prepair for testing
mkdir -p bb-test/dir1/dir2
cd bb-test
echo file3-content > dir1/dir2/file3
tar -cf a.tar dir1
mkdir out-coreut-2 out-busybo-2

# let's try!
        tar -xf a.tar -C out-coreut-2 --exclude dir2
busybox tar -xf a.tar -C out-busybo-2 --exclude dir2

# see difference
echo "" && tree out-coreut-2
echo "" && tree out-busybo-2

cd ..

And the output on my machine:

BusyBox v1.36.0 (2023-01-10 00:00:00 UTC) multi-call binary.
...

out-coreut-2
└── dir1

2 directories, 0 files

out-busybo-2
└── dir1
    └── dir2
        └── file3

3 directories, 1 file
2
  • Is this a bug of BusyBox? Should I report it?
    – kkocdko
    Commented Apr 3, 2023 at 2:59
  • If there's no high version of busybox included in your distro's repo, try to download 1.35 prebuilt binary from busybox official site.
    – kkocdko
    Commented Apr 3, 2023 at 3:14

2 Answers 2

-1

Use --exclude dir1/dir2 works fine, but Why?

busybox tar has no --exclude option. See busybox(1). So it can't and won't work. On my installed Debian 11, if I use --exclude I get this error message :

tar: unrecognized option '--exclude'
BusyBox v1.30.1 (Debian 1:1.30.1-6+b3) multi-call binary.

The output of your code (besides the error message) is

out-coreut-2
└── dir1

1 directory, 0 files

out-busybo-2

0 directories, 0 files

Note though that an incorrect typing could get you with something :

busybox tar xf a.tar -C out-busybo-2 exclude dir1/dir2

This asks to extract dir1/dir2 and exclude. Exclude does not exist in archive, there is an error message, but dir1/dir2 does exist in the archive and gets extracted.

Is there a way to exclude any directory named dir2 with busybox's tar?

No. not with a simple command.

You may busybox rm -rf dir1/dir2 after extraction, provided there is enough space on the device you're going to extract the files to.

If there were some other content in the dir1 directory, you could eventually list the archive, filter out ^dir1/dir2 and use the result as the list of files to extract. Something like this

# prepare data
rm -rf dir1
mkdir -p dir1/dir2 dir1/dir3
: >dir1/file1
: >dir1/dir2/file2
: >dir1/dir3/file3
busybox tar cf b.tar dir1
rm -rf dir1
# extract everything but dir1/dir2
busybox rm -rf out-busybo-2
busybox mkdir out-busybo-2
busybox tar xC out-busybo-2 -f b.tar $(
  busybox tar tf b.tar |
    busybox grep -ve ^dir1/dir2/ -e '^dir1/$' -e '/.*/.'
)

Result :

out-busybo-2/
└── dir1
    ├── dir3
    │   └── file3
    └── file1

But if you have filename with spaces in the archive, this won't work. Also there need to be at least one other element in dir1 for this to work. And there are probably some other corner cases where this will fail.

-e '/.*/.' is added to limit the number of elements produced by the tar tf command.

3
  • 1
    Current BusyBox does support --exclude in its tar command. The question uses version 1.36. Commented Mar 22, 2023 at 9:32
  • interesting. I just used a Debian 11 as op did, without noticing version 1.36. I guess my whole answer could be discarded.
    – exore
    Commented Mar 22, 2023 at 10:23
  • It could indeed. Commented Mar 23, 2023 at 8:04
-1

There is no "busybox's tar" as such. tar is a binary file with a huge number of modes, options and whatnot. Busybox is a binary which has the capability to pretend it's another binary like tar. It's often used in embedded systems or similar just to save space. As a jack-of-all-trades binary, it only contains limited set of functionalities available in the original binaries it replaces.

As for the question, this seems to work:

busybox tar -xf a.tar -C out-busybo-2 --exclude */dir2

Result:

out-coreut-2
└── dir1

1 directory, 0 files

out-busybo-2
└── dir1

1 directory, 0 files
4
  • 1
    Which version of busybox ? and does it work if you make sure there is no existing dir1/dir2 because you did not quote */dir2 which might get expanded by you shell, or removed, depending on you shell settings.
    – exore
    Commented Mar 22, 2023 at 8:47
  • I tried with 1.30.1-6b3 that comes with Deb 11, which didn't recognize --exclude at all. Built 1.36.0 and tested the script OP posted. The modified command did exclude dir2 also in busybox. However modifying the script to add more directories it's not working as well, just trying to figure out what's going on here :-) Interestingly also the older busybox version does have --exclude PATTERN, so it's not as straight-forward as it seems. Commented Mar 22, 2023 at 8:55
  • */dir2 in your code is unquoted and it probably is expanded by the shell before busybox starts. busybox tar probably sees --exclude dir1/dir2. The OP has already stated that "--exclude dir1/dir2 works fine". IMO your code is what the OP has tried, only in disguise. Commented Mar 22, 2023 at 9:18
  • @KamilMaciorowski Heh... not trying to copy or disguise OP:s thing but figure out how to get all directories named "dir2" excluded regardless of the directory structure and depth :-) And why it seems to be failing in v1.30. Thanks for the expansion pointer. Commented Mar 22, 2023 at 9:35

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .