4

Background: I am working in Automator on a wrapper to a command line utility. I need a way to separate an arbitrary number of file paths delimited by a single space from a single string, so that I may remove all but the first file path to pass to the program.

Example input string:

/Users/bobby/diddy dum/ding.mp4 /Users/jimmy/gone mia/come back jimmy.mp3 ...

Desired output:

/Users/bobby/diddy dum/ding.mp4

Part of the problem is the inflexibility on the Automator end of things. I'm using an Automator action which returns unescaped POSIX filepaths delimited by a space (or comma). This is unfortunate because: 1. I cannot ensure file/folder names will not contain either a space or comma, and 2. the only inadmissible character in Mac OS X filenames (as far as I can tell) is :. There are options which allow me to enclose the file paths in double or single quotes, or angle brackets. The program itself accepts the argument of the aforementioned input string, so there must be a way of separating the paths. I just do not have a keen enough eye to see how to do it with sed or awk.

At first I thought I'll just use sed to replace every [space]/ with [newline]/ and then trim all but the first line, but that leaves the loophole open for folders whose names end with a space. If I use the comma delimiter, the same happens, just for a comma instead. If I encapsulate in double or single quotation marks, I am opening another can of worms for filenames with those characters.

This is the relevant part of my Automator workflow:

image/link

-- UPDATE --

I was able to achieve what I wanted in a rather roundabout way. It's hardly elegant but here is working generalized code:

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

All this trouble because the default IFS doesn't count "emptiness" between the spaces as words, but rather collapses them all.

1 Answers1

1

This shell code will concatenate segments of the input until they form a valid file (path) name:

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

This assumes that the named files already exist (and your script can "see" them; i.e., can search the directories they are in) and it will still fail if a name contains multiple consecutive spaces (e.g., "diddy dum" is OK, but "diddy  dum" is not).

glenn jackman
  • 27,524