4

Справочная информация: я работаю в 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 по умолчанию не считает пустоты между пробелами словами, а сворачивает их все.

1 ответ1

1

Этот шелл-код объединяет сегменты ввода, пока они не сформируют правильное имя файла (путь):

file=""
sep=""
for word in $path
do
    file="$file$sep$word"
    if [[ -f "$file" ]]
    then
        break
    fi
    sep=" "
done
echo "first file: '$file'"

Это предполагает, что названные файлы уже существуют (и ваш скрипт может "видеть" их; т. Е. Может искать каталоги, в которых они находятся), и он все равно не будет работать, если имя содержит несколько последовательных пробелов (например, « diddy dum » в порядке но " diddy  dum " нет).

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .