我正在尝试编写一个可以从 Caja(Nautilus 的克隆)的上下文菜单中运行的脚本。其目的是将文件管理器中选择的文件传递给给定程序(例如 7zip)。系统变量 中提供了所选文件的列表$CAJA_SCRIPT_SELECTED_FILE_PATHS
,以换行符分隔。我想将此变量的每一行作为参数传递给程序,即使它们包含空格。
在引号包装失败后,我尝试了以下行:
echo "$CAJA_SCRIPT_SELECTED_FILE_PATHS" | xargs -d "\n" 7z a archive.7z
虽然它适用于 7zip,但我更改了脚本,以便将参数传递给我编写的程序,但出现了问题,所以我想要一种在终端中执行此脚本以从程序中获取输出的方法。我正在使用xterm -hold -e
,但我无法使带有管道的命令以这种方式执行,因为 shell 会尝试通过管道从 xterm 输出。我还尝试了 shell 重定向(通过添加> log.txt
到行尾),它为 7zip 的通常输出创建了一个文件,但为我的程序创建了一个空白文件,该文件在终端中输出消息很好。
最后,我想要一个兼容 POSIX(或其他标准)的解决方案,以便它在 BSD 和 Linux 上以相同的方式工作。
编辑:为了澄清,我想改变这样的事情:
/path/with/a space
/another/path
假设我会从这样的事情中得到什么:
char *argv[]={"/path/with/a space", "/another/path"};
EDIT2:这就是接收参数的程序应该是这样的,而不是外壳程序!
答案1
如果您愿意使用 bash,您可以设置IFS
换行并read
从此处字符串拆分CAJA_SCRIPT_SELECTED_FILE_PATHS
为数组。然后,您可以单独或在循环中访问数组元素(使用"${a[@]}"
)。嵌入的空间将被保留。
CAJA_SCRIPT_SELECTED_FILE_PATHS='a
b c
d
f
g'
IFS=$'\n' read -d '' -r -a a <<< "$CAJA_SCRIPT_SELECTED_FILE_PATHS"
printf "%s\n" "${a[0]}"
a
printf "%s\n" "${a[1]}"
b c
printf "%s\n" "${a[@]}"
a
b c
d
f
g
答案2
这是读取 stdin 并在换行符上分割的方法,保持空白完整:
我用破折号测试过
#!/bin/dash
while IFS= read -r line; do
set -- "$@" "$line"
done
printf "have arg '%s'\n" "$@"
答案3
当我试图从格伦·杰克曼的回答中得到一些有用的东西时,我弄清楚了 $IFS 是什么。看来这就是我所需要的。
我现在有这个脚本:
#!/bin/sh
IFS='
'
uxterm -hold -e ./program_to_test $CAJA_SCRIPT_SELECTED_FILE_PATHS
./program_to_test
我通过替换我编写的 BASH 脚本来确认它的工作原理,该脚本通过单独的突出显示来打印其参数。当我在 Caja 中运行上面的脚本时,出现了一个 xterm 窗口,并且所选文件的路径全部突出显示,路径之间突出显示有间隙,但文件名中的单词之间没有间隙。因此,这使得每一行都成为一个参数。
事实上,我很惊讶有一种方法不需要像 Bourne 一样的 shell 之外的任何工具。也许我还没有给予这个工具足够的信任。