2

Lets say we want to find a certain files , use tar on them and delete them. I tried using

touch "mycompress.bz2.tar"
find . \( -name "*.c" -o -name "*.sh*" \) -exec tar ujf "mycompress.bz2.tar" {} "+" \; -exec rm {} \;

But executing this my terminal just get closed. How can I implement this in a correctly?

  • The find(1) manpage suggests -exec command {} + , without a ;. What happens if you remove the first \; ? – JigglyNaga May 13 '16 at 9:16
5

There are several issues with your command.

The first one is a compressed archived cannot be updated. You would need to first create a uncompressed archive, update it and finally compress it.

The second one is the tar syntax is incorrect, the first -exec clause should use either the + terminator or the \; one, but not both.

The third one is more subtle and occur if you keep the + terminator, the second -exec clause will be executed for each file on sequence while the first one will wait for the list of files to save to fill the environment string to be launched. When this happen, all the files to be stored by the first -exec will have already been deleted by the second -exec so tar will fail and you'll have lost all of your files.

As there is no doubt you are using GNU tar, here is a simple way to achieve what you want :

tar --files-from <(find . \( -name "*.c" -o -name "*.sh*" \)) \
    --remove-files -cjf mycompress.bz2.tar

GNU tar is documented to remove the files only after they have been saved:

$ man gtar
...
       --remove-files
              remove files after adding them to the archive
...

Note that the command I suggested will fail to process files with an embedded new line but that should be quite an unlikely event.

  • 1
    If that works, then this should, too: find . \( -name "*.c" -o -name "*.sh*" \) -print0 | xargs --null tar --remove-files -cjf mycompress.bz2.tar. – Michael Vehrs May 13 '16 at 9:56
  • 1
    @schily I made it very clear my answer was requiring GNU tar. I didn't used the portable -I because I was already using the --remove-files anyway so used the more explicit --file-from long option. – jlliagre May 13 '16 at 10:10
  • 1
    It seems that you did not visit a UNIX system since a longer time. There are of course UNIX systems that are based on the original sources but added support for -j aprox. 10 years ago. And yes, I know that gtar has some compatibility problems from not following the UNIX tar command line syntax. – schily May 13 '16 at 10:25
  • 2
    @schily It looks like you are here only to self promote your software and troll other answers so I won't feed you any more. – jlliagre May 13 '16 at 10:32
  • 1
    @schily I'm quite sure the OP uses Linux Mint or similar Ubuntu Gnu/Linux. – jlliagre May 13 '16 at 11:57
-3

With one of the usual tar implementations, this does not work.

There is a free tar implementation since 1982 which is called star.

star added a built-in find utility in 2005 based on my libfind.

You call star -c -f file.out -find . \( -name "*.c" -o -name "*.sh*" \)

The rules for the built in find are simple: everything to the right side of -find follows the command line rules for find(1).

See http://schilytools.sourceforge.net/index.html

and the star man page at: http://schilytools.sourceforge.net/man/man1/star.1.html

There is a separate source (see web-site), but the most recent and best version is currently part of the schilytools.

Please keep in mind that your wish to remove the files while archiving them is higly risky as there may be a problem with your command and then you would have removed files that you cannot use with a second try anymore. I thus recommend to first use my proposal to archive the files and later call:

rm $(star -t -tpath < file.out)

This will only remove files that have been successfully put into the archive.

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.