Чтобы передать имя файла с пробелами в скрипт оболочки в macOS, заключите путь в кавычки как один аргумент при запуске скрипта, а затем используйте "$1" внутри скрипта. Например, ./process-file.sh "/Users/sam/Documents/Quarterly Report.pdf" передает одно имя файла; без кавычек оболочка разделит его на несколько аргументов. Этот метод также работает с путями, содержащими другие специальные символы оболочки, если они правильно заключены в кавычки.

Запуск скрипта с путем в качестве одного аргумента

В Терминале заключите полное имя файла или путь в двойные кавычки, включая содержащие его каталоги, и укажите имя скрипта отдельно:

./process-file.sh "/Users/sam/Documents/Quarterly Report.pdf"

Обратная косая черта перед каждым пробелом также подходит для простого ввода пути вручную: ./process-file.sh /Users/sam/Documents/Quarterly\ Report.pdf. Заключение всего пути в кавычки более читабельно и менее подвержено ошибкам, особенно если путь содержит несколько пробелов. Кавычки являются синтаксисом оболочки; они объединяют путь в один аргумент и не становятся частью имени файла, получаемого скриптом. Оболочка выполняет разбиение на слова после подстановок (expansions), поэтому путь без кавычек может быть разделен по пробелам. Bash Reference Manual: Quoting

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

./process-file.sh "Quarterly Report.pdf"

Путь должен указывать на существующий файл относительно каталога, из которого вы запускаете команду. Если сам скрипт не является исполняемым, вызовите его с помощью оболочки, например: bash process-file.sh "/Users/sam/Documents/Quarterly Report.pdf". Любой из этих вариантов передает путь в качестве аргумента; скрипту требуется разрешение на чтение файла, а также он должен корректно обрабатывать любые другие необходимые права доступа.

Безопасное использование аргумента внутри скрипта

Сохраните это под именем process-file.sh:

#!/bin/bash

if [ "$#" -ne 1 ]; then
  printf 'Usage: %s FILE\n' "$0" >&2
  exit 2
fi

file=$1
if [ ! -f "$file" ]; then
  printf 'Not a regular file: %s\n' "$file" >&2
  exit 1
fi

printf 'Received one file: %s\n' "$file"

Скрипт проверяет, что он получил ровно один аргумент, проверяет, что путь указывает на обычный файл, и выводит полученный путь. $# — это количество аргументов; $1 — первый из них. Сохраняйте подстановки переменных в кавычках — "$file" — при передаче пути в команду или при использовании его в условиях проверки. В противном случае оболочка может разбить значение, содержащее пробелы, на отдельные слова и воспринять символы подстановки как маски имен файлов. В руководстве по Bash описаны позиционные параметры, а также этапы разбиения на слова и подстановки имен файлов в оболочке. Bash Reference Manual: Positional Parameters and Shell Expansions

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

for file in "$@"; do
  printf 'Received: %s\n' "$file"
done

Не используйте для этих целей $* или не заключенный в кавычки $@: они могут объединить или непреднамеренно разбить значения аргументов. Если скрипт ожидает ровно один файл, оставьте проверку на один аргумент и передавайте один путь в кавычках.

Когда команду оболочки запускает AppleScript

Команда AppleScript do shell script принимает текстовую строку, содержащую код оболочки. Если объединить путь непосредственно в эту команду, путь вида /Users/sam/Quarterly Reports/report.pdf будет интерпретирован как несколько отдельных слов оболочки. Apple рекомендует использовать quoted form как способ формирования текста, безопасного для интерпретации оболочкой, включая строки с пробелами и встроенными символами кавычек. Apple: Calling Command-Line Tools

Если путь известен заранее, заключите его в кавычки с помощью quoted form of перед конкатенацией:

set filePath to "/Users/sam/Quarterly Reports/report.pdf"
set safePath to quoted form of filePath
do shell script "/path/to/process-file.sh " & safePath

Полученная команда передаст скрипту один аргумент пути. Если путь получен из диалога выбора файла, сначала преобразуйте выбранный элемент в путь POSIX, а затем заключите его в кавычки:

set filePath to POSIX path of (choose file)
do shell script "/path/to/process-file.sh " & quoted form of filePath

В справочнике AppleScript от Apple этот шаблон демонстрируется для выбранной папки, а также отмечается, что quoted form корректно обрабатывает и встроенные одинарные кавычки. AppleScript Language Guide: Commands Reference

Устранение распространенных ошибок

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

Если скрипт получает путь правильно, но последующая команда внутри него завершается ошибкой, проверьте аргументы и этой команды. Заключение в кавычки в команде запуска не защищает автоматически переменную без кавычек внутри скрипта: используйте конструкции вида some-command "$file". В AppleScript не добавляйте кавычки вокруг пути вручную; объединяйте quoted form of пути с командой оболочки. Это относится только к синтаксическому разбору оболочки. Это не делает несуществующий путь действительным, не предоставляет права доступа к файлу и не гарантирует, что вызываемая программа сможет обработать данный файл.

Источники