1

Я пишу скрипт для собственных нужд, чтобы отсортировать папку "Загрузки" на моем Mac в bash. Я передаю параметры функции: исходный каталог, целевой каталог и массив расширений файлов, которые я хочу переместить. Моя проблема в том, что когда функция находится в строке "найти", она копирует только один файл с таким расширением, но когда я удаляю все переменные и помещаю параметры напрямую, это работает нормально. В чем дело ?

 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


  }

1 ответ1

5

Каждый аргумент функции является скаляром, и вы пытаетесь передать массив. Когда ты пишешь

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

затем moveFaster получает пять аргументов: $src , $dst , foo , bar и qux . Если вы напишите moveFaster "$src" "$dst" "$a" то в функцию передается только первый элемент массива, поскольку $a по себе расширяется до первого элемента массива. Кроме того, ваше присваивание typ делает его скалярной переменной.

Поскольку вы передаете один массив функции, вы можете объявить, что он состоит из всех оставшихся параметров.

moveFaster () {
  src="$1"
  dst="$2"
  shift 2
  typ=("$@")
  …
}

На заметку о том, что ваш сценарий не получится впечатляюще, если какое-либо из имен файлов содержит пробелы или символы-заглушки (?*\[). Чтобы избежать этого, соблюдайте это простое правило программирования оболочки: всегда ставьте двойные кавычки вокруг подстановок переменных (если вы не понимаете, почему они не должны присутствовать в конкретном случае).

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
}

Кроме того, вы можете сделать это достаточно легко с помощью только функций bash, если у вас bash версии 4 или выше. Параметр extglob позволяет использовать расширенные шаблоны глобусов, такие как @(PATTERN1|PATTERN2) . Опция globstar позволяет **/PATTERN сопоставлять файлы, чье имя соответствует PATTERN в подкаталогах рекурсивно.

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

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .