背景:我正在 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
此 shell 代码将连接输入的各个部分,直到它们形成有效的文件(路径)名称:
文件=“” 九月=”” 对于 $path 中的单词 做 文件=“$文件$sep$word” 如果[[-f“$文件”]] 然后 休息 菲 九月=“” 完毕 echo "第一个文件:'$file'"
这假定命名的文件已经存在(并且您的脚本可以“看到”它们;即可以搜索它们所在的目录),并且如果名称包含多个连续的空格(例如,“ diddy dum
” 是可以的,但“ diddy dum
” 不可以),它仍然会失败。