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.

Let's say I want to execute several commands with similar flags such as:

du -sh / --exclude=/dir1 --exclude=/dir2 --exclude=/dir3/dir4
tar cvf archive / --exclude=dir1 --exclude=dir2 --exclude=dir3/dir4

I want to reuse the sequence of --exclude flags and make the code more clean by e.g. saving these flags to a variable.

So afterwards above commands look like

du -sh / "$EFLAGS"
tar cvf archive / "$EFLAGS"

Note that tar excludes files and directories relative to the given directory.

What is the best and cleanest solution?

Background

I want to backup my system using tar and exclude some directories that I don't need.

share|improve this question
2  
It looks good to me except i think you should not use quotes. –  LatinSuD Jun 25 at 18:42
2  
^this - you need the variable to expand into several words - so you'll need the word-splitting of $IFS - which is partly what quotes are designed to protect against. –  mikeserv Jun 25 at 18:45
add comment

3 Answers 3

up vote 4 down vote accepted

You can try this:

$ echo -e / --exclude=/dir1 --exclude=/dir2 --exclude=/dir3/dir4
/ --exclude=/dir1 --exclude=/dir2 --exclude=/dir3/dir4
$ echo !!:3-$
echo --exclude=/dir1 --exclude=/dir2 --exclude=/dir3/dir4
--exclude=/dir1 --exclude=/dir2 --exclude=/dir3/dir4

Here we use bash history expansion:

  • !! refer to the last command
  • 3-$ refer to the 3rd parameter to the last

You should turn on bash history expansion features in your script, which are disabled in non interactive shell:

set -o history
set -o histexpand
share|improve this answer
    
is history affected if I input a command from another terminal while my script works? Or the same? –  polym Jun 25 at 18:52
1  
I think there is no affect. –  Gnouc Jun 25 at 18:54
add comment

In Bash, a very clean way is to use arrays:

myflags=( --exclude=/dir1 --exclude=/dir2 --exclude=/dir3/dir4 )
tar cvf archive / "${myflags[@]}"

They can handle spaces and any other funny characters:

myflags=( "--exclude=/a dir/with spaces" $'--exclude=/a dir/with\nnewlines' )
tar cvf archive / "${myflags[@]}"

They can be forged too, e.g., you want to exclude all subdirectories of directory /this/one, that contain the letter g:

exclude_dirs=( /this/one/*g* )
myflags=( "${exclude_dirs[@]/#/--exclude=}" )
tar cvf archive / "${myflags[@]}"
share|improve this answer
add comment

I would have added this as a comment except that I haven't figured out how to format comments well!

Anyway, I believe you're 90% of the way there. Try:-

EFLAGS="--exclude=/dir1 --exclude=/dir2"
du -sh / $EFLAGS
tar cvf archive / $EFLAGS

Quotes needed in the first line as there are spaces involved.

No quotes when using the variable so that it splits the arguments on spaces.

If there are spaces in the excluded directory names you'll need to escape them.

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.