tar --exclude with curly braces


 
Thread Tools Search this Thread
Top Forums Shell Programming and Scripting tar --exclude with curly braces
# 1  
Old 08-07-2012
tar --exclude with curly braces

I'm having trouble understanding the exclude option in tar. From some web sites, it seems one is able to exclude several strings by enclosing them in curly brackets. However it seems to be "random" what gets excluded when using the curlies.

I've been using the exclude-from=myfile option in a script but would like to inline myfile into a variable and use $exclude={this,that,the_other} with the --exclude=$exclude option to keep the script self-contained.

Simple examples to illustrate:

Say I have directories C and D and want to make them into a tar file.
Code:
tar -cvf mytar.tar C D

This works.

Now for the sake of argument, I want to exclude C.
Code:
tar -cvf mytar.tar C D --exclude=C

This works as expected (C is excluded).

Now I bring in the curlies...
Code:
tar -cvf mytar.tar C D --exclude={C}

This does not exclude C, which is not what I expected.

If I try to exclude a subdirectory of C, it also doesn't work.
Code:
tar -cvf mytar.tar C D --exclude={C/subdir}

Nothing is excluded.

If I exclude both C and D, then it does work (both are excluded).
Code:
tar -cvf mytar.tar C D --exclude={C,D}

Any idea how I can get the same functionality as --exclude-from with --exclude?

Last edited by Franklin52; 08-08-2012 at 05:12 AM.. Reason: Please use code tags for data and code samples
# 2  
Old 08-07-2012
Reading thru the gnutar (version 1.26) source I can't see any intended support for the {} matching.

I'd say this is probably an unsupported "feature" you should probably stick with the documented method of using multiple --exclude arguments for each pattern to exclude.

---------- Post updated at 11:32 AM ---------- Previous update was at 11:17 AM ----------

Thought: Could the shell be expanding your parameters?
Code:
$ echo {C}
{C}
$ echo {C,D}
C D

# 3  
Old 08-07-2012
Chubler_XL's thought is right on the mark. The shell running the command supports brace expansion and it is generating multiple --exclude options.

When there's no comma between the braces, there's no brace expansion. When there's no brace expansion, the pattern passed to tar includes the braces themselves. Unless there's a filename with literal braces, that exclude will not match anything.

To confirm: set -x; tar .... ; set +x

Regards,
Alister
# 4  
Old 08-08-2012
Quote:
Originally Posted by Chubler_XL
Reading thru the gnutar (version 1.26) source I can't see any intended support for the {} matching.

I'd say this is probably an unsupported "feature" you should probably stick with the documented method of using multiple --exclude arguments for each pattern to exclude.
Thanks, at least I'm not going crazy Smilie Searching around a little more, it seems there is a way to include multiple arguments. Basically you create a temp file with the patterns to exclude and point --exclude-from (or -X) to that file. See below.

Code:
#!/bin/bash

include="C D"
exclude="C xyz"

tar -cvf mytar.tar $include -X <(for i in ${exclude}; do echo $i; done)



---------- Post updated at 03:20 PM ---------- Previous update was at 02:23 PM ----------


My mistake, this script has problems with wildcard expansion. E.g. if you wanted to exclude *.tar then it would expand the asterisk prematurely rather than passing it to the tar command. Here is a workaround - not too pretty but could be worse.

Code:
include="C D"
exclude=("C" "*.tar") # note this is an array now

mycommand="tar -cvf mytar.tar $include"
for i in `seq 1 ${#exclude[*]}`; do mycommand=$mycommand\ --exclude="${exclude[$i-1]}"; done

eval $mycommand

# 5  
Old 08-08-2012
What is the eval for?

Eval is to be avoided. If someone puts `rm -Rf ~/` in your filenames, eval will execute that.
# 6  
Old 08-08-2012
Quote:
Originally Posted by majest
I've been using the exclude-from=myfile option in a script but would like to inline myfile into a variable and use $exclude={this,that,the_other} with the --exclude=$exclude option to keep the script self-contained.

... <snip> ...

Any idea how I can get the same functionality as --exclude-from with --exclude?
Sure, just use mutliple --exclude options.

Quote:
Originally Posted by majest
Code:
include="C D"
exclude=("C" "*.tar") # note this is an array now

mycommand="tar -cvf mytar.tar $include"
for i in `seq 1 ${#exclude[*]}`; do mycommand=$mycommand\ --exclude="${exclude[$i-1]}"; done

eval $mycommand

It doesn't make much sense to resort to a dynamic, command-building process when the "variable" is constant data hardcoded into the script. Why not just add one --exclude pattern per pattern? Your script will be simpler, more readable, more efficient, and safer.

Still, if you're determined to store exclusion patterns in a variable, the following is much less complicated:
Code:
include='C D'
exclude='C
*.tar'

tar -cvf mytar.tar $include -X <(cat <<EOX
$exclude
EOX
)

This does not work with the only version of GNU tar that I have (an elderly 1.16, circa 2006). strace shows tar closing all file descriptors in the range 3 to 1023, sabotaging the shell's (bash) attempt to pass the cat process substitution on fd 63.

However, although I have not tested it, it should work with newer versions of GNU tar. A pair of 2007 commits removed both the function call and the function definition implementing the fd closures.

tar.git - GNU Tar - src/tar.c - (main): Don't call closeopen

tar.git - GNU Tar - src/misc.c - Don't include <sys/time.h>, <sys/resource.h>; no longer needed.

Regards,
Alister
# 7  
Old 08-08-2012
Quote:
Originally Posted by alister
Sure, just use mutliple --exclude options.



It doesn't make much sense to resort to a dynamic, command-building process when the "variable" is constant data hardcoded into the script. Why not just add one --exclude pattern per pattern? Your script will be simpler, more readable, more efficient, and safer.

Still, if you're determined to store exclusion patterns in a variable, the following is much less complicated:
Code:
include='C D'
exclude='C
*.tar'

tar -cvf mytar.tar $include -X <(cat <<EOX
$exclude
EOX
)

The reason for using eval $mycommand is so that other users can edit the top of the script where exclude and include are defined rather than having to read through the code. Your second construct is elegant - but does not work on OpenSuse 11.4.
Login or Register to Ask a Question

Previous Thread | Next Thread

10 More Discussions You Might Find Interesting

1. UNIX for Beginners Questions & Answers

Check string end with curly braces

file.txt apple apples{ applepicture apple9 apple cake{ abple apple_and_cake appleapple apple apple( and my script while read line; do if ]; then echo "$line" fi done <file.txt read (10 Replies)
Discussion started by: cmdcmd
10 Replies

2. Shell Programming and Scripting

When curly braces needed?

Hello, i was trying to find get a command to list duplicated files so i tried ls dir1 dir2 | awk '{x++}' and it didnt work. After a bit of searching online i found that it works without the curly braces ls dir1 dir2 | awk 'x++' I thought the curly braces were needed in awk so... (6 Replies)
Discussion started by: andy391791
6 Replies

3. Shell Programming and Scripting

Curly braces in sed

Hi, I have below command in one of the script. Can you please let me know what does the curly braces do over here \{1,\}. The remaining part of the code atleast I am able to understand. sed -n 's/.*\-\()\{1,\}\)\-.*/\1/p' (13 Replies)
Discussion started by: tostay2003
13 Replies

4. Shell Programming and Scripting

How to remove newline, tab, spaces in curly braces.. :( Pls Help?

Hi Everyone, in the below "xyz (Exception e)" part... after the curly braces, there is a new line and immediately few tabs are present before closing curly brace. xyz (Exception e) { } note: there can be one or more newlines between the curly braces. My desired output should be ... (6 Replies)
Discussion started by: NY_777
6 Replies

5. Shell Programming and Scripting

** EMERGENCY ** Having trouble with curly braces.. :( Pls Help

Hi Everyone, in the below "xyz (Exception e)" part... after the curly braces, there is a new line and immediately few tabs are present before closing curly brace. xyz (Exception e) { } note: there can be one or... (1 Reply)
Discussion started by: NY_777
1 Replies

6. UNIX for Dummies Questions & Answers

How do I pull the value between curly braces?

Hi everyone, I've got a file that looks like this: uid{508}pid{22224}pname{/PPROGRAM/pprgramx -profile:LIVE -serv:as ... I want to pull the value of pid between the curly braces, or 22224 in this example. pid is always the second pair of curly braces, but the length of the number is... (7 Replies)
Discussion started by: Scottie1954
7 Replies

7. Shell Programming and Scripting

sed in windows does not parse curly braces

Hi everyone: I'm stuck at this point, could you guys please give me some hints about what I am doing wrong in the following script, I'm using sed for windows: sed ^"$ {^ a^ STRINGTABLE DISCARDABLE^ BEGIN^ #define CLIENT_MODULE, "%CLIENT_MODULE%"^ #define CLIENT_ID, "%CLIENT_ID%"^... (1 Reply)
Discussion started by: edgarvm
1 Replies

8. Shell Programming and Scripting

find -regex not recognizing curly braces

Must be a bug or something. Whether I escape them or not, it will not work. No matter what I set the minimum and maximum to nothing gets caught. For instance: find / -regex "/.{0, 50}.*" -maxdepth 1 or find / -regex "/.\{0, 50\}.*" -maxdepth 1 should pretty much catch everything residing within... (4 Replies)
Discussion started by: stevensw
4 Replies

9. Shell Programming and Scripting

Curly braces assigned to variables

Hi, Im pretty new to Unix. I came across a script which was using PLSQL inside a script and there was an unusual thing mentioned. there was a variable assigned as P_CUR=${1} and one more as V_TAGFILE="$1" Couldnt find the difference. Also the variables were used in PLSQL... (1 Reply)
Discussion started by: njks68
1 Replies

10. Shell Programming and Scripting

Use of curly braces with variables

Hi, I am new to shell scripting.I have worked somewhat with Perl though. I am not able to find what the second line does and how does it do. <code> FP_RUNNING=`service filepool status` FP_RUNNING=${FP_RUNNING%% *} <\code> After the first line,the variable FP_RUNNING stores '1 FilePool... (2 Replies)
Discussion started by: abhinavsinha
2 Replies
Login or Register to Ask a Question