Может кто-нибудь объяснить, что делает "${files[@]}"

Посмотрите на эту технику с bash 4.4:

function myf { 
  if ! [ -t 0 ];then 
    declare -a args=\($(</dev/stdin)\);
    set -- "${args[@]}"; 
  fi;
  for i in "$@";do 
    echo "$i";
    echo -----;
  done 
}

Тестирование:

$ function myf { if ! [ -t 0 ];then declare -a args=\($(</dev/stdin)\);set -- "${args[@]}"; fi;for i in "$@";do echo "$i";echo -----;done }
$ myf 1 "2 3" 4
1
-----
2 3
-----
4
-----

$ echo $'1 "2 3" 4'|myf
1
-----
2 3
-----
4
-----

Тот же результат можно получить и с:

$ echo 1 \"2 3\" 4 |myf
$ echo 1 "'2 3'" 4 |myf

Но echo 1 "2 3" 4 не будет работать, потому что bash игнорирует двойные кавычки в этом синтаксисе:

$ echo 1 "2 3" 4
1 2 3 4
1
30.08.2016, 22:20
3 ответа

Короче говоря, вы создаете массив files и расширяете его.

Вы читаете это так:

VAR = ... означает, что вы назначаете переменную. VAR = (...) означает, что вы назначаете массив bash переменной.

$ (...) означает, что вы запускаете команду и получаете ее вывод, в вашем случае список файлов, которые соответствуют заданному шаблону, которые настолько стары, а затем назначают каждый файл элементу в bash множество.

$ {...} означает, что вы читаете значение переменной, например:

$ SOMEVAR="a value"
$ echo "${SOMEVAR}"
a value

В bash $ VAR и $ {VAR} эквивалентны, но нотация $ {VAR} позволяет вам делать некоторые дополнительные вещи. В частности, echo "$ {VAR} iable" расширит переменную $ VAR и объединит ее со строкой iable , тогда как echo $ VARiable ] попытается расширить переменную $ VARiable . Вы также можете выполнить некоторую расширенную замену , используя нотацию $ {...} .

В нашем случае мы читаем файловую переменную с помощью $ {file ...} . Затем [...] указывает, что мы читаем массив bash . Итак, мы пытаемся получить доступ к элементу массива файлов, бит внутри [...] сообщает нам, какие элементы, это может быть 1 для доступа к первому элементу, 2 для доступа ко второму и так далее (массивы bash индексируются с 1, а не с 0). @ означает все элементы, поэтому мы пытаемся получить доступ ко всем элементам массива bash под названием file .

Вы можете попробовать это со следующим:

% ARRAY=("a value" "another value" "fred")
% for x in "${ARRAY[@]}"; do echo "$x"; done
a value
another value
fred

Преимущество использования массивов вместо строк, разделенных пробелами, заключается в том, что вы можете включать пробелы в значения, как указано выше. Таким образом, в вашем случае каждый файл в массиве files будет рассматриваться как отдельный аргумент, а пробелы в именах файлов будут обрабатываться правильно.

По сути, ваш snipit находит и собирает список файлов и передает их как отдельные аргументы команде tar.

0
28.01.2020, 01:11

files = (...) создает массив имен файлов

Синтаксис "$ {files [@]}" означает _каждый элемент массива; т.е. каждое найденное имя файла. Обратите внимание на окружение "..." , это важно для предотвращения разделения некоторых имен файлов.

(Это может привести к сбою, если в любом имени файла есть возврат каретки).

0
28.01.2020, 01:11

files = (...) создает массив строк в ksh , который создал этот синтаксис, и в оболочках, которые позже приняли его, например bash и другие.

$ (find / var / cdrs -maxdepth 1 -name \ *. C * R -mtime +150) создает список путей, разделенных пробелами, соответствующих указанным условиям. Однако, если имя файла содержит один из символов IFS, обычно пробел, табуляцию и перевод строки, имя файла будет разделено на части, а затем будет неправильно сохранено в массиве.

"$ {files [@]}" расширяется до списка строк, в которых каждый элемент заключен в кавычки. Цитирование элементов здесь бесполезно, поскольку массив в любом случае не может содержать пробелов, табуляции или возврата каретки, как указано в предыдущем абзаце. Затем этот синтаксис можно немного упростить с помощью $ {files [*]} .

0
28.01.2020, 01:11

Теги

Похожие вопросы