Моя цель - создать сервис в Automator с использованием AppleScript или Javascript, который заменяет все недопустимые символы в выбранном имени файла ()[\/:"*?<>|]+_ и пробелы на тире (-) и делает имя файла строчным.
Похоже на забавный проект, где ты застрял?



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Это довольно просто с помощью 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
Я пытаюсь внедрить ваш код в рабочий процесс, а затем запустить службу через контекстное меню, выбрав имя flie. Но после завершения кода я получаю уведомление: new-foo - abcd-b-r.ext
Это линия display dialog. Просто удали его.
Но имя файла не меняется.
Если вы получаете new-foo--abcd-b-r.ext, имя имеет изменилось. Результат - в trimmedFileName. Это просто пример, fileName жестко запрограммирован. Вы должны встроить код в свою среду.
Это должен быть принятый ответ. Работает отлично! Есть ли способ упростить его и убрать «строчную» часть кода?
@JordanHe Удалите строку lowercaseString() и в следующей строке замените nsLowerCaseFileName's на nsFileName's
Замена недопустимых символов в имени файла / папки может быть достигнута с помощью сценария Bash Shell в вашем сервисе Automator.
Следующие шаги описывают, как этого добиться:
File> New в строке меню.Service и нажмите ChooseВ верхней части области холста настройте его параметры следующим образом:
Выберите Library вверху панели / столбца слева:
В поле поиска введите: Get Select Finder items и перетащите действие 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:
Replace Impermissible Chars в контекстном меню, чтобы запустить его.В качестве альтернативы в Finder:
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) на более чем один символ вместо одного дефиса -.
Большое спасибо, РобК! Все работает как ожидалось.
Здесь два отличных решения. Но поскольку каждая проблема обычно имеет множество решений, я предлагаю другое:
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Автомат, помещая 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
Удачи с этим.