【问题标题】:Replacing invalid characters in the filename with dashes using AppleScript使用 AppleScript 将文件名中的无效字符替换为破折号
【发布时间】:2018-05-02 12:21:08
【问题描述】:

我的目标是使用 AppleScript 或 Javascript 在 Automator 中创建服务,它将所选文件名 ()[\\/:"*?<>|]+_ 和空格的所有无效字符替换为破折号 (-) 并使文件名小写。

【问题讨论】:

    标签: javascript regex applescript automator


    【解决方案1】:

    借助正则表达式和桥接到 AppleScriptObjC 的 Foundation Framework 非常容易。

    use AppleScript version "2.4" -- Yosemite (10.10) or later
    use scripting additions
    
    use framework "Foundation"
    
    set fileName to "New(Foo)*aBcd<B|r.ext"
    
    set nsFileName to current application's NSString's stringWithString:fileName
    set nsLowerCaseFileName to nsFileName's lowercaseString()
    set trimmedFileName to (nsLowerCaseFileName's stringByReplacingOccurrencesOfString:"[()[\\/:\"*?<>|]+_]" withString:"-" options:(current application's NSRegularExpressionSearch) range:{location:0, |length|:nsLowerCaseFileName's |length|()}) as text
    display dialog trimmedFileName
    

    【讨论】:

    • 我正在尝试将您的代码实施到工作流中,而不是通过上下文菜单运行服务,同时选择苍蝇的名称。但是代码完成后我收到通知:new-foo--abcd-b-r.ext
    • 这是display dialog 行。只需将其删除。
    • 但是文件名没有变化。
    • 如果您收到new-foo--abcd-b-r.ext,则名称更改。结果在trimmedFileName 中。这只是一个例子,fileName 是硬编码的。您必须将代码嵌入到您的环境中。
    • @JordanHe 删除lowercaseString() 行并在下一行将nsLowerCaseFileName's 替换为nsFileName's
    【解决方案2】:

    这里有两个很好的解决方案。但是由于每个问题通常都有很多解决方案,因此我提供了另一种解决方案:

        property alphabet : "abcdefghijklmnopqrstuvwxyz-ABCDEFGHIJKLMNOPQRSTUVWXYZ"
        --------------------------------------------------------------------------------
        rename from "HELLO World+Foo(\"Bar\")new.ext"
        --------------------------------------------------------------------------------
        ### HANDLERS
        #
        # rename from:
        #   Receives a text string and processes it for invalid characters, which
        #   get replaced with the specified replacement string (default: "-"),
        #   returning the result
        to rename from filename given disallowed:¬
            invalidCharSet as text : "[()[\\/:\"*?<>|]+_] ", replaceWith:¬
            replacementStr as text : "-"
            local filename
            local invalidCharSet, replacementStr
    
            set my text item delimiters to {replacementStr} & ¬
                the characters of the invalidCharSet
    
            text items of the filename as text
    
            makeLowercase(the result)
        end rename
    
    
        # makeLowercase():
        #   Receives a text string as input and returns the string formatted as
        #   lowercase text
        to makeLowercase(str as text)
            local str
    
            set my text item delimiters to ""
    
            if str = "" then return ""
    
            set [firstLetter, otherLetters] to [¬
                the first character, ¬
                the rest of the characters] of str
    
    
            tell the firstLetter to if ¬
                it is "-" or ¬
                it is not in the alphabet then ¬
                return it & my makeLowercase(the otherLetters)
    
            considering case
                set x to (offset of the firstLetter in the alphabet) mod 27
            end considering
    
            return character x of the alphabet & my makeLowercase(the otherLetters)
        end makeLowercase
    

    此代码可用于 Run AppleScript Automator 操作,将 rename from... 放在 on run {input, parameters} 处理程序中,其余代码放在它之外。它可以遵循在 Finder 中为其提供文件列表的操作,或者如果它作为 服务 运行,它可以直接从工作流的输入中接收其输入>

        property alphabet : "abcdefghijklmnopqrstuvwxyz-ABCDEFGHIJKLMNOPQRSTUVWXYZ"
    
        on run {input, parameters}
            tell application "Finder" to repeat with f in input
                set the name of f to (rename from f)
            end repeat
        end run
    
        to rename from ...
            .
            .
        end rename
    
        to makeLowercase(str as text)
            .
            .
        end makeLowercase
    

    【讨论】:

      【解决方案3】:

      可以通过在 Automator 服务中使用 Bash Shell 脚本来替换文件/文件夹名称中不允许的字符。

      以下步骤描述了如何实现这一点:

      配置自动机

      1. 启动自动机
      2. 键入⌘N,或从菜单栏中选择File > New
      3. 选择Service并点击Choose
      4. 在画布区域的顶部配置其设置如下:

      5. 选择左侧面板/列顶部的Library

        • 在搜索字段中输入:Get Select Finder items 并将Get Select Finder items 操作拖到画布区域中。

        • 在搜索字段中输入:Run Shell 并将Run Shell Script 操作拖到画布区域中。

      6. 如下配置Run Shell Script操作的顶部:

      7. 将以下 Bash 脚本添加到 Run shell Script 操作的主要区域:

        #!/usr/bin/env bash
        
        # The following characters are considered impermissible in a basename:
        #
        #  - Left Square Bracket:   [
        #  - Right Square Bracket:  ]
        #  - Left Parenthesis:      (
        #  - Reverse Solidus:       \
        #  - Colon:                 :
        #  - Quotation Mark         "
        #  - Single Quotation Mark  '
        #  - Asterisk               *
        #  - Question Mark          ?
        #  - Less-than Sign         <
        #  - Greater-than Sign      >
        #  - Vertical Line          |
        #  - Plus Sign              +
        #  - Space Character
        #  - UnderScore             _
        #
        #  1. Sed is utilized for character replacement therefore characters listed
        #     in the bracket expression [...] must be escaped as necessary.
        #  2. Any forward slashes `/` in the basename are substituted by default with
        #     a Colon `:` at the shell level - so it's unnecessary to search for them.
        #
        declare -r IMPERMISSIBLE_CHARS="[][()\\:\"'*?<>|+_ ]"
        declare -r REPLACEMENT_STRING="-"
        
        # Obtain the POSIX path of each selected item in the `Finder`. Input must
        # passed to this script via a preceding `Get Selected Finder Items` action
        # in an Automator Services workflow.
        declare selected_items=("$@")
        
        declare -a sorted_paths
        declare -a numbered_paths
        
        # Prefix the POSIX path depth level to itself to aid sorting.
        for ((i = 0; i < "${#selected_items[@]}"; i++)); do
          numbered_paths+=("$(echo "${selected_items[$i]}" | \
              awk -F "/" '{ print NF-1, $0 }')")
        done
        
        # Sort each POSIX path in an array by descending order of its depth.
        # This ensures deeper paths are renamed before shallower paths.
        IFS=$'\n' read -rd '' -a sorted_paths <<<  \
            "$(printf "%s\\n" "${numbered_paths[@]}" | sort -rn )"
        
        
        # Logic to perform replacement of impermissible characters in a path basename.
        # @param: {Array} - POSIX paths sorted by depth in descending order.
        renameBaseName() {
          local paths=("$@") new_basename new_path
        
          for path in "${paths[@]}"; do
        
            # Remove numerical prefix from each $path.
            path="$(sed -E "s/^[0-9]+ //" <<< "$path")"
        
            # Replaces impermissible characters in path basename
            # and subsitutes uppercase characters with lowercase.
            new_basename="$(sed "s/$IMPERMISSIBLE_CHARS/$REPLACEMENT_STRING/g" <<< \
                "$(basename "${path}")" | tr "[:upper:]" "[:lower:]")"
        
            # Concatenate original dirname and new basename to form new path.
            new_path="$(dirname "${path}")"/"$new_basename"
        
            # Only rename the item when:
            # - New path does not already exist to prevent data loss.
            # - New basename length is less than or equal to 255 characters.
            if ! [ -e "$new_path" ] && [[ ${#new_basename} -le 255 ]]; then
              mv -n "$path" "$new_path"
            fi
          done
        }
        
        renameBaseName "${sorted_paths[@]}"
        
      8. Automator 服务/工作流程的已完成画布区域现在应该如下所示:

      9. 键入 ⌘S,或从菜单栏中选择 File > Save。我们将文件命名为Replace Impermissible Chars


      运行服务:

      1. Finder中:

        • 选择单个文件或文件夹,然后ctrl+单击显示上下文菜单
        • 在上下文菜单中选择Replace Impermissible Chars 服务来运行它。
      2. 或者,在Finder中:

        • 选择多个文件和/或文件夹,然后ctrl+单击显示上下文菜单
        • 在上下文菜单中选择Replace Impermissible Chars 服务来运行它。

      注意事项:

      1. Finder 将允许在一次选择的多达 1000 个文件/文件夹上运行服务。

      2. 如果这是您创建的第一个 Automator 服务,您可能(如果我没记错的话!)需要重新启动计算机才能通过上下文弹出窗口使用它菜单。

      3. 如果满足以下两个条件之一,Bash Shell 脚本将不会替换文件/文件夹名称中不允许的字符:

        • 如果文件/文件夹名称与生成的新文件/文件夹名称匹配。例如:假设我们有一个名为hello-world.txt 的文件,并且在同一个文件夹中有一个名为hello?world.txt 的文件。如果我们在hello?world.txt 上运行服务,它的名称将不会被更正/更改,因为这可能会覆盖已经存在的hello-world.txt 文件。

        • 如果生成的文件名是 &gt;= 到 255 个字符。当然,这只有在您将 REPLACEMENT_STRING 值(在 Bash/Shell 脚本中)更改为多个字符而不是单个连字符 - 时才会发生。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-08-28
        • 1970-01-01
        • 2012-12-25
        • 1970-01-01
        相关资源
        最近更新 更多