Моя цель - создать сервис в Automator с использованием AppleScript или Javascript, который заменяет все недопустимые символы в выбранном имени файла ()[\\/:"*?<>|]+_
и пробелы на тире (-
) и делает имя файла строчным.
Замена недопустимых символов в имени файла на тире с помощью AppleScript
- Удачи с этим. 02.05.2018
- Похоже на забавный проект, где ты застрял? 02.05.2018
Ответы:
Замена недопустимых символов в имени файла / папки может быть достигнута с помощью сценария Bash Shell в вашем сервисе Automator.
Следующие шаги описывают, как этого добиться:
Настройка Automator
- Запускать автомат
- Введите ⌘N или выберите
File
>New
в строке меню. - Выберите
Service
и нажмитеChoose
В верхней части области холста настройте его параметры следующим образом:
Выберите
Library
вверху панели / столбца слева:В поле поиска введите: Получить элементы Select Finder и перетащите действие
Get Select Finder items
в область холста.В поле поиска введите: Run Shell и перетащите действие
Run Shell Script
в область холста.
Настройте верхнюю часть действия
Run Shell Script
следующим образом:Добавьте следующий сценарий 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[@]}"
Завершенная область холста вашей службы / рабочего процесса Automator должна теперь выглядеть примерно так:
Введите ⌘S или выберите
File
>Save
в строке меню. Назовем файлReplace Impermissible Chars
.
Запуск службы:
В Finder:
- Select a single file or folder and then ctrl+click to show the contextual menu
- Выберите службу
Replace Impermissible Chars
в контекстном меню, чтобы запустить ее.
Либо в Finder:
- Select multiple files and/or folders and then ctrl+click to show the contextual menu
- Выберите службу
Replace Impermissible Chars
в контекстном меню, чтобы запустить ее.
Примечания:
Finder позволяет запускать Службу одновременно с 1000 выбранными файлами / папками.
Если это первая созданная вами служба Automator, вам возможно (если я правильно запомнил!) Потребуется перезагрузить компьютер, чтобы она стала доступной через контекстное всплывающее меню.
Сценарий Bash Shell не заменяет недопустимые символы в имени файла / папки, если выполняется одно из следующих двух условий:
Если имя файла / папки уже существует, которое совпадает с именем результирующего нового имени файла / папки. Например: Допустим, у нас есть файл с именем
hello-world.txt
и в той же папке файл с именемhello?world.txt
. Если мы запустим Сервис наhello?world.txt
, его имя не будет исправлено / изменено, так как это потенциально может перезаписатьhello-world.txt
файл, который уже существует.Если результирующее имя файла составляет
>=
до 255 символов. Это, конечно, может произойти только в том случае, если вы измените значениеREPLACEMENT_STRING
(в сценарии Bash / Shell) на несколько символов, а не только на один дефис-
.
Это довольно просто с помощью Regular Expression и Foundation Framework, соединенного с AppleScriptObjC.
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
display dialog
. Просто удали его. 02.05.2018 new-foo--abcd-b-r.ext
, имя изменилось. Результат есть в trimmedFileName
. Это просто пример, fileName
жестко запрограммирован. Вы должны встроить код в свою среду. 02.05.2018 lowercaseString()
и в следующей строке замените nsLowerCaseFileName's
на nsFileName's
29.12.2020 Здесь два отличных решения. Но поскольку каждая проблема обычно имеет множество решений, я предлагаю другое:
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
Этот код можно использовать в действии Запустить AppleScript Automator, поместив rename from...
в обработчик on run {input, parameters}
, а остальную часть кода - за его пределы. Он может следовать за действием, которое предоставляет ему список файлов в Finder, или он может получать свои входные данные непосредственно из входных данных рабочего процесса, если он запускается как Служба em >.
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