Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

Find command giving this output

[root@localhost /]# find var/log/ -iname anaconda.*
var/log/anaconda.log
var/log/anaconda.xlog
var/log/anaconda.yum.log
var/log/anaconda.syslog
var/log/anaconda.program.log
var/log/anaconda.storage.log

After combining with tar it's showing this output

[root@localhost /]# find var/log/ -iname anaconda.* -exec tar -cvf file.tar {} \;
var/log/anaconda.log
var/log/anaconda.xlog
var/log/anaconda.yum.log
var/log/anaconda.syslog
var/log/anaconda.program.log
var/log/anaconda.storage.log

But while listing tar file its showing only single file

[root@localhost /]# tar -tvf file.tar 
-rw------- root/root    208454 2012-02-27 12:01 var/log/anaconda.storage.log

What I am doing wrong here?

with xargs I am getting output

[root@localhost /]# find var/log/ -iname anaconda.* | xargs tar -cvf file1.tar

2nd doubt

While typing / in front of var, means find /var/log why its giving this mesaage tar: Removing leading `/' from member names

[root@localhost /]# find /var/log/ -iname anaconda.* -exec tar -cvf file.tar {} \;
tar: Removing leading `/' from member names
/var/log/anaconda.log
tar: Removing leading `/' from member names
/var/log/anaconda.xlog
tar: Removing leading `/' from member names
/var/log/anaconda.yum.log
tar: Removing leading `/' from member names
/var/log/anaconda.syslog
tar: Removing leading `/' from member names
/var/log/anaconda.program.log
tar: Removing leading `/' from member names
/var/log/anaconda.storage.log

In simple form what is the difference between in these 2

find var/log and find /var/log

share|improve this question
    
This is semi+off topic, but going forward with the find command, you should quote the search term. It works without sometimes but not always. –  nerdwaller Dec 1 '12 at 15:39
add comment

4 Answers

up vote 5 down vote accepted

Note that find will call the -exec action for every single file it finds.

If you run tar -cvf file.tar {} for every single file find outputs, this means you'll overwrite file.tar every time, which explains why you end up with one archive left that only contains anaconda.storage.log — it's the last file find outputs.

Now, you actually want to append the files to the archive instead of creating it each time (this is what the -c option does). So, use the following:

find var/log/ -iname "anaconda.*" -exec tar -rvf file.tar {} \;

The -r option appends to the archive instead of recreating it every time.

Note: Replace -iname anaconda.* with -iname "anaconda.*". The asterisk is a wildcard and can be expanded by your shell before find even sees it. To prevent this expansion, wrap the argument in double quotes.


As for tar removing leading /: The archive should only contain relative file names. If you added files with a leading /, they would be stored as absolute file names, literally meaning /var/… on your computer, for example.

IIRC this is simply a precaution for tar implementations other than GNU, and it's safer this way because you won't overwrite your actual data in /var/… when you extract the archive if it contains relative filenames.

share|improve this answer
2  
But note that if you tried taring to an actual tape archive this way, adding one file at at time, rewinding the tape, then rereading the whole thing each time to get to the end, the whole thing would be ridiculously slow. Your solution is only suitable if you're writing the tar file to disk. –  Nicole Hamilton Dec 1 '12 at 14:55
1  
True, but I think we can safely disregard this situation ;) –  slhck Dec 1 '12 at 15:03
    
@slhck * is a wildcard that should match all the possibility right? but here find /var/log/ -iname anaconda* giving nothing and find /var/log/ -iname anaconda.* giving the output, why? –  max Dec 2 '12 at 6:49
    
When a wildcard is consumed, it won't be seen by find anymore. So if you have anaconda*, and in your current folder there's something named, for example, anaconda5 (matching this wildcard), the wildcard will be expanded, and find will see -iname anaconda5 instead of -iname anaconda*. Why the first doesn't work and the second does depends on what files are in your current directory. @max –  slhck Dec 2 '12 at 8:55
add comment

You a use something like

find var/log -print0 -iname 'anaconda.*' | tar -cvf somefile.tar -T - 

The -print0 and -T work together to allow filenames with spaces newlines etc. The final - tells tar to read the input filenames from stdin.

share|improve this answer
    
You've omitted the -name option, causing your solution to tar the whole directory. If that's what you want, you could do it more easily as tar -cvf file.tar var/log without using find at all. –  Nicole Hamilton Dec 1 '12 at 15:45
    
@NicoleHamilton: You're right and it's easily fixed (which you could have done too). It doesn't affect what I was demonstrating which is that you can use - as the input file to tar so the output of find can be piped into it. –  Iain Dec 1 '12 at 15:56
    
+1 Piping the list to tar is a good idea. It's definitely the best solution if you expect the pathnames may have spaces. I would even describe it as the best technically, since it's both reliable and efficient. But it requires additional special knowledge of both find and tar. I prefer command substitution pretty much only because it's a more general tool: Learn how to use it once, then use it everywhere. (But I concede, I'm on Windows with a shell where it always works.) Apologies if I seemed rude. –  Nicole Hamilton Dec 1 '12 at 17:49
    
@NicoleHamilton: Do you not run the risk of Argument List Too Long Error because the command substitution expands onto the command line ? –  Iain Dec 1 '12 at 18:07
1  
You already got your +1. Be happy. :) Long command lines are always the bane of the process creation i/f on any OS. I remember arguing with Mark Lucovsky at Microsoft in the early 90s that their 32K Unicode characters limit on NT was too small and having him complain I had no idea how many more bytes it would take to store lengths as longs rather than shorts everywhere in the kernel. Sigh. The more general case solutions when the arg list is too long are to do more in the shell (if possible; in mine it is) or use xargs. –  Nicole Hamilton Dec 1 '12 at 18:33
show 1 more comment

Question 1

Your command fails because tar is taking each of the files found and archiving them into file.tar. Each time it does so, it will overwrite the previously created file.tar.

If what you want is one archive with all the files, then simply run tar directly, there is no need for find (and yes, this works for files with spaces in their names):

tar -vcf file.tar /var/log/anaconda*   

Question 2

The two commands are completely different:

  • find var/log will search a directory called var/log which is a subdirectory of your current directory, it is equivalent to find ./var/log (notice the ./).

  • find /var/log will search a directory called /var/log which is a subdirectory of the root, /.

The leading / message is from tar, not find. It means that it is removing the first / of your file names to make absolute paths into relative. This means that the file from /var/log/anaconda.error will be extracted to ./var/log/anaconda.error when you untar the archive.

share|improve this answer
add comment

Try this:

tar -cvf file.tar `find var/log/ -iname "anaconda.*"`

You were trying to use find to -exec tar. But the way the -exec option works, it runs that command once for each matching file it finds, causing tar to overwrite the tar file it produces each time. That's why you only ended up with the last one. Also, you need to put quotes around the pattern you specify to find so that the shell doesn't expand it before passing it to find.

Using command substitution with backticks (or using $(...) notation if you prefer), the entire list of names produced by find is pasted back onto the command line as arguments to tar, causing it to write them all at once.

share|improve this answer
2  
This could end up bad if find outputs files with spaces in their name, newlines or globbing characters. This is bound to fail – piping stdout from find is rarely a good idea. mywiki.wooledge.org/ParsingLs –  slhck Dec 1 '12 at 14:42
3  
@slhck, piping stdout from find is in fact usually a good idea, as very clearly explained in the page you linked to in your comment :). It is in fact the recommended way to do things. You should just use some tricks (such as read -r of -print0) as I did in my answer. –  terdon Dec 1 '12 at 14:47
3  
@slhck This is why file and directory names in Unix and Linux have traditionally avoided spaces in names. It's also why, on Windows, where names with spaces are common, I added an additional command substitution notation to my own Hamilton C shell using double backticks that treating the whole lines (possibly including spaces) as single words to be pasted back onto the command line. Unfortunately, none of the Unix shells have that feature. –  Nicole Hamilton Dec 1 '12 at 14:49
1  
They might have traditionally avoided it, but with files being created in the user space through GUIs, you can't neglect files with spaces anymore and treat them as second class citizens (just because it's Unix). It's nice you included that in your shell, but it's for Windows, and Unix shells don't particularly need that feature if you simply use the right syntax and take proper precautions. Which is why I've posted my comment in the first place. –  slhck Dec 1 '12 at 15:06
1  
No, but in other places it might very well happen. That's why it's a good idea to program defensively – better be safe than sorry. Also, visitors finding this question might not necessarily have the exact same problem and wonder why the command they've found here appeared to work for this very case but failed for them. I'll leave it up to you to fix the command, I just thought it was important mentioning it because many people run into this issue sooner or later. –  slhck Dec 1 '12 at 16:04
show 5 more comments

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.