Как я могу использовать цикл внутри команды?

Я пишу сценарий оболочки, содержащий команду, которая принимает несколько каталогов в качестве входных аргументов, разделенных пробелами (например, ls ). Я хотел бы заполнить эти аргументы из переменной, но не знаю, как обеспечить, чтобы слова типа «for» не интерпретировались как аргументы. Вот пример, который выражает мою идею:

 #!/bin/bash dirs=" $HOME/Documents $HOME/Music " ls \ for dir in $dirs do "$dir " done 

В:

 dirs=" $HOME/Documents $HOME/Music " 

Вы назначаете строку (содержащую пробелы и символы новой строки и любые символы $HOME могут содержать) для скалярной переменной ( $dirs ).

Затем вы хотите передать список каталогов в ls , то есть несколько аргументов. Поэтому вам нужно как-то разбить эту строку на список аргументов, чтобы перейти к ls . Как вы собираетесь разбить его? О пробелах и переводах строк? Что делать, если $HOME содержит пробелы или символы новой строки?

У оболочек POSIX есть оператор расщепления, на самом деле у них есть оператор split + glob, который вы вызываете, оставляя переменную без кавычек. К счастью, по умолчанию разделение выполняется в пространстве и новой строке (и вкладке). Таким образом, вы можете сделать:

 IFS=' '' ' # space and newline set -f # disable globbing as we want only the # splitting part of the split+glob operator ls -- $dirs 

Но здесь, поскольку нам нужен список, лучше всего было бы сохранить элементы в переменную типа списка, а не объединять их в строку, чтобы разделить ее позже.

Оболочки POSIX имеют массив позиционных параметров ( $1 , $2 …) для этого:

 #! /bin/sh - set -- ~/Documents ~/Music ls -- "$@" 

Или, если вы не возражаете сделать ваш скрипт медленнее и менее переносимым, используйте оболочку с переменными массива, такими как bash :

 #! /bin/bash - files=( ~/Documents ~/Music ) ls -- "${files[@]}" 

Или zsh :

 #! /bin/zsh - files=( ~/Documents ~/Music ) ls -- $files