Справочная информация: я работаю в Automator над оболочкой для утилиты командной строки. Мне нужен способ отделить произвольное количество путей к файлам, разделенных одним пробелом, от одной строки, чтобы я мог удалить все пути, кроме первого, для передачи в программу.
Пример входной строки:
/Users/bobby/diddy dum/ding.mp4 /Users/jimmy/gone mia/come back jimmy.mp3 ...
Желаемый результат:
/Users/bobby/diddy dum/ding.mp4
Частично проблема заключается в негибкости конца Automator. Я использую действие Automator, которое возвращает неэкранированные пути к файлам POSIX, разделенные пробелом (или запятой). Это прискорбно, потому что: 1. Я не могу гарантировать, что имена файлов / папок не будут содержать ни пробела, ни запятой, и 2. единственный недопустимый символ в именах файлов Mac OS X (насколько я могу судить) это :
Есть варианты, которые позволяют мне заключать пути к файлам в двойные или одинарные кавычки или угловые скобки. Программа сама принимает аргумент вышеупомянутой входной строки, поэтому должен быть способ разделения путей. У меня просто недостаточно глаз, чтобы понять, как это сделать с помощью sed
или awk
.
Сначала я подумал, что просто использую sed
для замены каждого [space]/
на [новую строку [newline]/
а затем обрежу все, кроме первой строки, но это оставляет лазейку открытой для папок, имена которых заканчиваются пробелом. Если я использую разделитель запятых, то происходит то же самое, только для запятой. Если я заключаю в двойные или одинарные кавычки, я открываю другую банку червей для имен файлов с этими символами.
Это важная часть моего рабочего процесса Automator:
-- ОБНОВИТЬ --
Я смог добиться того, чего хотел, довольно окольным путем. Это вряд ли элегантно, но здесь работает обобщенный код:
path="/Users/bobby/diddy dum/ding.mp4 /Users/jimmy/gone mia/come back jimmy.mp3"
# using colon because it's an inadmissible Mac OS X
# filename character, perfect for separating
# also, unlike [space], multiple colons do not collapse
IFS=:
# replace all spaces with colons
colpath=$(echo "$path" | sed 's/ /:/g')
# place words from colon-ized file path into array
# e.g. three spaces -> three colons -> two empty words
j=1
for word in $colpath
do
filearray[$j]="$word"
j=$j+1
done
# reconstruct file path word by word
# after each addition, check file existence
# if non-existent, re-add lost [space] and continue until found
name=""
for seg in "${filearray[@]}"
do
name="$name$seg"
if [[ -f "$name" ]]
then
echo "$name"
break
fi
name="$name "
done
Все это связано с тем, что IFS по умолчанию не считает пустоты между пробелами словами, а сворачивает их все.