使用 bash 脚本对下载文件夹进行排序

1 bash shell

我正在编写脚本以满足我自己的需要,以便在 bash 中对我的 mac 上的下载文件夹进行排序。我传递给函数参数:源目录、目标目录和要移动的文件扩展名数组。我的问题是,当函数在“查找”行中时,它只复制一个具有该扩展名的文件,但是当我删除所有变量并直接输入参数时,它可以正常工作。这是怎么回事 ?

 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


  }
Run Code Online (Sandbox Code Playgroud)

Gil*_*il' 5

函数的每个参数都是一个标量,而您正在尝试传递一个数组。当你写

a=(foo bar qux)
moveFaster "$src" "$dst" "${a[@]}"
Run Code Online (Sandbox Code Playgroud)

然后moveFaster接收五个参数:$src$dstfoobarqux。如果你写,moveFaster "$src" "$dst" "$a"那么只有数组的第一个元素被传递给函数,因为$a它自己扩展到数组的第一个元素。此外,您的赋值typ使其成为标量变量。

由于您将单个数组传递给函数,因此您可以声明它包含所有剩余参数。

moveFaster () {
  src="$1"
  dst="$2"
  shift 2
  typ=("$@")
  …
}
Run Code Online (Sandbox Code Playgroud)

与此相关的是,如果任何涉及的文件名包含空格或通配符 ( ?*\[) ,您的脚本将严重失败。为了避免这种情况,请遵守这个简单的 shell 编程规则:始终在变量替换周围加上双引号(除非您明白为什么它们不能出现在特定情况下)。

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
}
Run Code Online (Sandbox Code Playgroud)

顺便说一句,如果您有 bash 版本 4 或更高版本,您可以仅使用 bash 功能就可以相当容易地做到这一点。该extglob选项允许扩展 glob 模式,例如@(PATTERN1|PATTERN2). 该globstar选项允许**/PATTERN匹配名称PATTERN在子目录中递归匹配的文件。

shopt -s extglob globstar
mkdir -p /common/destination/directory
mv /path/to/source/**/@(*.txt|*.html|README) /common/destination/directory
Run Code Online (Sandbox Code Playgroud)