I've encountered with kinda strange behaviour of 7z (or bash, I don't know yet.). With the following script:

find /home/user  -type f -name "*.pdf" | cut -c 10- > /home/user/exclude_list2.lst;
lst1=" -x@/home/user/exclude_list2.lst -xr!'*.config/*' -xr!'*.cache/*' "
command=$(/usr/bin/7z a $lst1 -v2048M arch0.7z /home/user);

also, the last two lines can be easily substituted with single line:

/usr/bin/7z a $lst1 -v2048M arch0.7z /home/user

I've also tried :

command="/usr/bin/7z a  $lst1  -v2048M arch0.7z /home/dh ;"

I receive a 'arch0.7z' file, but folders .config and .cache are being included still, while:

find /home/user  -type f -name "*.pdf" | cut -c 10- > /home/user/exclude_list2.lst;
/usr/bin/7z a -x@/home/user/exclude_list2.lst -xr!'*.config/*' -xr!'*.cache/*' -v2048M arch0.7z /home/user ;"

generates a file with properly excluded folders.

So, I wonder, what is the difference between the line expanded from variable:

/usr/bin/7z a $lst1 -v2048M arch0.7z /home/user

and the one I've typed as is:

 /usr/bin/7z a -x@/home/user/exclude_list2.lst -xr!'*.config/*' -xr!'*.cache/*' -v2048M arch0.7z /home/user

Is there any reason for such significant changes in 7z workflow?

migrated from serverfault.com Sep 25 '14 at 19:28

This question came from our site for system and network administrators.


Your original form

command=$(/usr/bin/7z a $lst1 -v2048M arch0.7z /home/user);

will mean that $command contains the output of the 7zip run, as var=$(...) will store the output of a command into the variable.


/usr/bin/7z a $lst1 -v2048M arch0.7z /home/user

is a not a substitution, but a correction of the error in the script.

Anyway, to the real issue.

If you run the variable assignment in the shell, you will notice the following:

$ lst1=" -x@/home/user/exclude_list2.lst -xr!'*.config/*' -xr!'*.cache/*' "
-bash: !'*.config/*': event not found

So, you have an error in this line, as the shell will do variable substitution etc. when double quotes "..." are used. The problematic item is the !, as it used by bash to refer to previous commands in its history. Use single quotes instead: '...'

$ lst1=' -x@/home/user/exclude_list2.lst -xr!'*.config/*' -xr!'*.cache/*' '
$ echo $lst1
-x@/home/user/exclude_list2.lst -xr!*.config/* -xr!*.cache/*

That's something I wasn't expecting for.

lst1=' -xr@/home/me/exclude_list2.lst -xr!'*.config/*' -xr!'*.cache/*' -xr!'*.local/*' '
7z a $lst1 -v2048M arch0.7z /home/me

do the trick, while I was thinking that single quote in -xr!'.config/' will end the variable assignment, it actually works as a part of argument. Also, works perfectly if my variable is an array.

By the way, escaping with "!" won't work, 7z says "Error: Incorrect command line" for it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy