1

I'm writing script for my own needs to sort Downloads folder on my mac in bash. I pass to the function parameters: source directory, destination directory and array of file extensions I want to move. My problem is that when function is in "find" line then it copies just one file with that extension but when I remove all variables and I put parameters directly then it works fine. What's going on ?

 function moveFaster(){
 clear
 src=1ドル
 dst=2ドル
 typ=3ドル
 if [ ! -d $dst ]
 then
 mkdir $dst
 fi
 for i in "${typ[@]}"
 do
 find $src -name "${i}" -exec mv {} ${dst} \;
 done
 }
asked Oct 2, 2011 at 18:29
1
  • Put 'set -x' towards the top, so it will echo everything it does. Commented Oct 2, 2011 at 19:00

1 Answer 1

5

Each argument to a function is a scalar, and you're trying to pass an array. When you write

a=(foo bar qux)
moveFaster "$src" "$dst" "${a[@]}"

then moveFaster receives five arguments: $src, $dst, foo, bar and qux. If you write moveFaster "$src" "$dst" "$a" then only the first element of the array is passed to the function, because $a on its own expands to the first element of the array. Furthermore, your assignment to typ makes it a scalar variable.

Since you're passing a single array to the function, you can declare that it consists of all the remaining parameters.

moveFaster () {
 src="1ドル"
 dst="2ドル"
 shift 2
 typ=("$@")
 ...
}

On a related note, your script will fail spectacularly if any of the file names involved contains whitespace or globbing characters (?*\[). To avoid this, respect this simple shell programming rule: always put double quotes around variable substitutions (unless you understand why they must not be present in a particular case).

function moveFaster(){
 src="1ドル"
 dst="2ドル"
 typ=("$@")
 if [ ! -d "$dst" ]; then mkdir -- "$dst"; fi
 for i in "${typ[@]}"; do
 find "$src" -name "${i}" -exec mv {} "${dst}" \;
 done
}

As an aside, you can do this reasonably easily with bash features alone, if you have bash version 4 or above. The extglob option allows extended glob patterns such as @(PATTERN1|PATTERN2). The globstar option allows **/PATTERN to match files whose name matches PATTERN in subdirectories recursively.

shopt -s extglob globstar
mkdir -p /common/destination/directory
mv /path/to/source/**/@(*.txt|*.html|README) /common/destination/directory
answered Oct 2, 2011 at 19:43

You must log in to answer this question.