将从 bash 个命令返回的路径名分配给 AppleScript 列表

Assign pathnames returned from bash command(s) to an AppleScript list

我想在 Applescript 中以列表的形式提示一个目录(递归)最近添加的 10 个文件的路径。这在 bash:

中工作正常
SAVEIFS=$IFS
IFS=$(echo -en "\n\b")

array=(`find . -type f -print0 | xargs -0 ls -t | head -n 10`)

echo "${array[*]}"

IFS=$SAVEIFS

我想将结果数组存储在 Applescript 变量中:

set l to (do shell script "______________")

如何将 bash 部分放入工作的 1-liner 中?也许还有一个仅适用于 Applescript 的解决方案?

当您从 AppleScript "shell out" 中分配给变量的值 class 时,(即名为 l 的变量在你的例子中)总是 text and not a list.

在您的场景中,您实际上是在捕获 find 实用程序等发送到 stdout (fd 1) 的路径名,Applescript 将其识别为 text

要转换每一行(即通过 bash 命令打印到 stdout 路径名 ),您需要使用助手 subroutine/function 如以下要点所示。

  set stdout to do shell script "/usr/bin/find " & quoted form of "/absolute/path/to/target/directory" & " -type f -print0 | xargs -0 ls -t | head -n 10"

  set latestList to transformStdoutToList(stdout)

  -- Test it's a proper AppleScript list.
  log class of latestList
  log (item 1 of latestList)
  log (item 2 of latestList)
  -- ...

  (**
   * Transforms each line printed to stdout to form a new list of pathnames.
   *
   * Pathname(s) may contain newline `\n` characters in any part, including
   * their basenames. Below we read each line, if it begins with a forward
   * slash `/` it is considered to be the start of a pathname. If a line does
   * not begin with a forward slash `/` it is considered to be part of the
   * prevous pathname. In this scenario the line is appended to previous item
   * of the list and the newline character `\n` is reinstated.
   *
   * @param {String} pathsString - The pathname(s) printed to stdout.
   * @return {List} - A list whereby each item is a pathname.
   *)
  on transformStdoutToList(pathsString)
    set pathList to {}
    repeat with aLine in paragraphs of pathsString
        if aLine starts with "/" then
            set end of pathList to aLine
        else
            set last item of pathList to last item of pathList & "\n" & aLine
        end if
    end repeat
    return pathList
  end transformStdoutToList

解释:

  1. 第一行阅读:

    set stdout to do shell script "/usr/bin/find " & quoted form of "/absolute/path/to/target/directory" & " -type f -print0 | xargs -0 ls -t | head -n 10"
    
    • 我们利用 AppleScript 的 do shell script 命令来执行您的 bash 命令。
    • 将 bash 命令的结果(通常是 路径名 的 multi-line 字符串)分配给名为 AppleScript 的变量stdout。分配给 stdout 的值的 class 将是 text - 您可以通过在脚本中临时添加以下行来验证这一点:

      log class of stdout
      
    • 注意:您需要重新定义当前读取的部分; /absolute/path/to/target/directory,带有您要搜索的 directory/folder 的真实绝对路径。您还会注意到此目标 pathname 前面有 & quoted form of - 这只是确保给定 pathname 中的任何 space 个字符 被正确解释。

  2. 第二行读:

    set latestList to transformStdoutToList(stdout)
    

    调用 transformStdoutToList 子例程,传入 stdout 的值,并将返回的结果分配给名为 latestList 的变量。分配给 latestList 的值的 class 将是 list。同样,您可以通过在脚本中临时添加以下行来验证这一点:

    log class of latestList
    
  3. transformStdoutToList子例程转换传递给它的每一行(即路径名)并形成一个新的list 路径名。请阅读上面代码中的注释以获得进一步的解释——您会注意到它成功地处理了任何可能包含换行符的 pathname(s)


补充说明:

前面提到的 transformStdoutToList 子例程包括一行:

set last item of pathList to last item of pathList & "\n" & aLine

"\n" 部分的存在是为了恢复 路径名 中可能存在的任何换行符。但是,当您在 AppleScript 编辑器 中编译脚本时,将显示如下:

set last item of pathList to last item of pathList & "
" & aLine

注意: 换行符,即 \n 部分已经消失,并创建了一个实际的 line-break.

这是正常的,脚本会产生预期的结果。但是,如果您想在 AppleScript 编辑器 中保留 "\n" 部分,请按如下所述更改您的首选项:

  1. Select AppleScript Editor > Preferences... 从菜单栏。
  2. Select Editing 选项卡。
  3. 单击 Formatting: Escape tabs and line breaks in strings 的复选框(即打开此选项)。

编辑:

How can I put the bash part into a working 1-liner

如果你必须有一个"1-liner"并且愿意牺牲可读性,那么你可以这样做:

set l to transformStdoutToList(do shell script "/usr/bin/find " & quoted form of "/absolute/path/to/target/directory" & " -type f -print0 | xargs -0 ls -t | head -n 10")

但是,您仍然需要使用前面提到的 transformStdoutToList 子例程,因此它也需要出现在您的脚本中。