Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I have the followin directory structure:

base/
   files/
   archives/
   scripts/

I want a script to run from scripts/, compress files that match results.*.log in files/ into a gzipped tar archive in archives/.

I'm trying the following command:

tar czfC ../archives/archive.tar.gz ../files results.*.log

But I get

tar: results.*.log: Cannot stat: No such file or directory
tar: Exiting with failure status due to previous errors

While

tar czfC ../archives/archive.tar.gz ../files results.a.log

works as expected. Also

tar czf ../archives/archive.tar.gz ../files/results.*.log

works the way I would like, except it adds the prefix files/ to the file and also emits a warning:

tar: Removing leading `../' from member names

So my conclusion is that tar globbing doesn't work properly when using the -C option. Any advice on how I make this work in a simple manner?

share|improve this question
add comment

6 Answers 6

There is no "tar globbing", the globbing is done by the shell. And the shell has no idea that tar -C somedir will do its work in somedir, any globs are expanded in the current directory.

share|improve this answer
    
Indeed, if results.a.log exists in the directory from which the script is run, it works. But I don't understand why this happens, since -C stands for change directory, so the current directory should be the one with results.a.log. I can't accept your answer because you don't offer a solution. –  Yuval Apr 6 '13 at 14:35
1  
The shell takes the command, expands globs in the current directory, manufactures the arguments from the above, and launches the tar program, which changes directory much later. Can't "solve" your problem, sorry. The only way out is to move into the directory where you want to glob, or do the globbing in the directory and save its results in a file or variable. –  vonbrand Apr 6 '13 at 14:46
add comment

Write it the more portable way:

(cd ../files && tar cf - results.*.log) | 
  gzip -9 > ../archives/archive.tar.gz
share|improve this answer
    
The glob will still be interpreted in the current directory, before the cd happens. –  vonbrand Apr 6 '13 at 16:50
    
@vonbrand, no, of course it won't. && is like ; or newline, it separates two commands. It's like saying that after running cd, any glob would expand files in the previous directory. –  Stéphane Chazelas Apr 6 '13 at 19:35
    
You are right. One never finishes learning. –  vonbrand Apr 6 '13 at 22:54
add comment

You can let find do the globbing and omit the 'change directory' option to tar by removing the files/ prefix before creating the tarfile.

The --no-recursion option to tar is optional since no directories are going to be archived.

cd base/scripts

# gnutar
# printf '%s\000' ../files/results.*.log |  # find alternative
find ../files -maxdepth 1 -type f -name "results.*.log" -print0 | 
   gnutar --transform="s|^\.\{0,1\}\.\{0,1\}/\{0,1\}files/||" -cf - --null --no-recursion -T - | 
   gzip -9 > ../archives/archive.tar.gz
gnutar -tf ../archives/archive.tar.gz | nl
gnutar -xzf ../archives/archive.tar.gz

# bsdtar
find ../files -maxdepth 1 -type f -name "results.*.log" -print0 | 
   bsdtar -s "|^\.\{0,1\}\.\{0,1\}/\{0,1\}files/||" -cf - --null --no-recursion -T - | 
   gzip -9 > ../archives/archive.tar.gz
bsdtar -tf ../archives/archive.tar.gz | nl
bsdtar -xzf ../archives/archive.tar.gz
share|improve this answer
add comment

I finally used

tar czfC ../archives/archive.tar.gz ../files `find ../files/results.*.log -printf "%f\n"`
share|improve this answer
    
While that may work for you, it's a pretty complex way to do it. Furthermore, it won't work with file names containing special characters such as whitespace. Use one of the sane methods that have been proposed in answers. –  Gilles Apr 8 '13 at 1:16
add comment

The way to do that is to write something like the following:

#!/bin/sh

cd ../files
tar zcf ../archives/archive.tar.gz results.*.log
cd ../scripts
share|improve this answer
add comment

It's not tar that does the globbing, it's the shell. You're first telling the shell to do globbing, then telling tar to change directories. Since tar is receiving a list of file names relative to the original directories, this doesn't work.

The easiest solution by far is to let the shell change the directory. Interactively:

cd ../files
tar czf ../archives/archive.tar.gz  results.*.log
cd -

In a script:

(
  cd ../files &&
    tar czf ../archives/archive.tar.gz  results.*.log
)

or

(
  cd ../files &&
    tar czf -  results.*.log
) >../archives/archive.tar.gz
share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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