Bash проблема с функцией, которая скрывает файлы - PullRequest
0 голосов
/ 30 апреля 2020

У меня есть эта функция

function hide {
    for f in "$@"; do
        if [[ ! ${f::1} == '.' ]]; then
            mv $f .$f
        fi
    done
}

, которая должна скрывать файл, переданный в качестве ввода, если он еще не скрыт.

Когда я использую его для файлов, имена которых содержат пробелы, например :

touch "ciao ciao"
hide ciao\ ciao

это не работает, и вместо этого я получаю эту ошибку:

usage: mv [-f | -i | -n] [-v] source target
       mv [-f | -i | -n] [-v] source ... directory

Я попытался изменить .$f на ."$f" в команде mv, но я все еще получаю ошибка.

Ответы [ 2 ]

3 голосов
/ 30 апреля 2020

Улучшение ответа @ rtx13:

  • Безопасная обработка полных путей
  • Приоритетное использование синтаксиса POSIX над спецификациями Bash.
#!/usr/bin/env sh

hide ()
{
  # Without in, for loop iterates arguments
  for path; do

    # Strips-out the leading directory path to keep file name only
    file="${path##*/}"

    # If file name starts with a dot, continue to next argument
    [ -n "${file##.*}" ] || continue

    # Strips out the trailing file name to keep the leading directory path only
    base="${path%/*}"

    # If base is same as file, then there is no leading dir, so prepend current
    if [ "$base" = "$file" ]; then
      base='.'
      path="./$path"
    fi

    # Performs the file rename
    mv --no-clobber -- "$path" "$base/.$file" # Always double quote variables expansion
  done
}

РЕДАКТИРОВАТЬ :

После хороших комментариев gniourf_gniourf .

  1. Упрощенно, но сохранил безвредный терминатор опций -- как привести к хорошей практике.
  2. Добавлено --no-clobber, чтобы не перезаписывать существующие файлы.
0 голосов
/ 30 апреля 2020

Для @Jetchisel вам нужно заключить переменные в кавычки при передаче аргументов в mv, чтобы обеспечить сохранение пробелов:

function hide {
    for f in "$@"; do
        if [[ ! ${f::1} == '.' ]]; then
            mv "$f" ".$f"  # <= note variable references are quoted
        fi
    done
}
...