I've found the following script on commandlinefu.com (the example is not online anymore):
rmbut() {
local x=("$@")
IFS=, rm -rf *[!"${x[*]}"]
}
It deletes all files and directories but the ones named on the command line.
Could you explain the following:
- What is happening on the first line?
$@
means all arguments, but why is it put inside parentheses? - I've read about
IFS
but never actually used it, what is its usage here? - What is 开发者_JAVA百科achieved with
*[!"${x[*]}"]
? I can't understand how to split it into something I know.
local x=("$@")
creates an array which is a copy of all the arguments ($@
is itself an array).
IFS=,
sets the internal field separator to a comma.
IFS=, rm -rf *[!"${x[*]}"]
says to remove all files that do not end in any character passed as arguments. Since *
is used as the index to the array and the variable is quoted it is expanded to a single string and the spaces that would normally separate the elements of the array are replaced by the contents of IFS
(a comma in this case).
rmbut a b c
resolves to rm -rf *[!a,b,c]
which would also not remove files that end in a comma.
I think the function could be simplified to:
rmbut() {
IFS= rm -rf *[!"$*"]
}
but its behavior would be subtly different. This version sets IFS
to null so the example above would resolve to rm -rf *[!abc]
which would remove files that end in a comma (a comma would have to be passed explicitly as an argument to preserve such files). However, that behavior could be returned by setting IFS=,
(it's simply not necessary to copy the array).
# create an array x, containing arguments to the function
local x=("$@")
# unset the IFS variable. This make double quoted arrays expand to single words w/o separators
IFS=
# remove files matching a pattern, i.e. not ending with a character from the array x
rm -rf *[!"${x[*]}"]
精彩评论