Как перезаписать все файлы в папке? - PullRequest
0 голосов
/ 05 января 2020

Я использую следующее для копирования файла:

on replace:sender

        set allFiles to choose file with prompt "Please select your file:" with multiple selections allowed
        repeat with theFile in allFiles

            tell application "Finder"
                set {name:fileName, name extension:nameExtension, file type:fileType} to theFile
                if fileType is "png" or nameExtension is "png" then
                    set myPng to "~/Documents" & fileName as POSIX file


                    else
                    delay 0.2
                    tell current application's NSAlert's alloc's init()
                        its setMessageText:"Replace Photo"
                        its setInformativeText:"The file \"" & fileName & "\" is not a PNG file!"
                        its setAlertStyle:2
                        its setShowsSuppressionButton:false
                        its beginSheetModalForWindow:theWindow completionHandler:(missing value)
                        return
                    end tell
                end if

                if exists myPng then
                    delay 0.2
                    tell current application
                        display alert"There is already an older item named \""& fileName &"\" at this location." message ¬
                        "Do you want to replace it with the newer \"" & fileName & "\" one you're moving?" buttons {"Cancel", "Replace"} default button "Replace" as critical

                        set response to button returned of the result
                        if response is "Replace" then
                            delay 0.2
                            do shell script "rm -rf " & quoted form of POSIX path of myPng & space & "~/Documents" & myPng with administrator privileges
                            do shell script "mv " & quoted form of POSIX path of theFile & space & "~/Documents" with administrator privileges
                        end if

                        if response is "Cancel" then
                            return
                        end if
                    end tell
                    else
                    do shell script "mv " & quoted form of POSIX path of theFile & space & "~/Documents" with administrator privileges
                end if
            end tell
        end repeat
    end replace:

Если в целевой папке есть файл с тем же именем, пользователь получает предупреждение, но происходит то, что происходит с каждым скопированным Если отображается это предупреждение, я хотел бы показать это предупреждение только один раз, точно так же, как это делает macOS, а затем, если пользователь нажмет кнопку «Заменить», все файлы будут заменены сразу.

Ответы [ 3 ]

1 голос
/ 05 января 2020

Вы также можете использовать NSAlert (как и раньше) с его кнопкой подавления и отслеживать состояние в обработчике, например (запустить на переднем плане в редакторе сценариев):

use AppleScript version "2.4" -- Yosemite (10.10) or later
use framework "Foundation"
use scripting additions

set buttonState to false

repeat -- forever, or at least until canceled
    if buttonState then
        display dialog "The suppression button state is currently " & buttonState buttons {"Cancel", "Reset", "OK"}
        if button returned of the result is "Reset" then set buttonState to false
    else
        tell current application's NSAlert's alloc's init()
            its setMessageText:"Alert"
            its setInformativeText:"This alert is going to keep showing until you choose otherwise."
            its setShowsSuppressionButton:true
            its (suppressionButton's setTitle:"Skip the alerts")
            its runModal()
            set buttonState to (its suppressionButton's state()) as boolean
        end tell
    end if
end repeat
1 голос
/ 06 января 2020

Ваш сценарий не компилируется, поэтому он не позволил мне протестировать его, чтобы действительно почувствовать, что вы делаете, поэтому я надеюсь, что я нахожусь в шаре с тем, что я придумал ниже .

Но, кроме этого, я буду тупым: ваш сценарий - беспорядок. У вас есть блок Finder , который содержит некоторый код AppleScriptObj C, а затем некоторые вызовы функций оболочки ... Я думаю, вам нужно выбрать one , а затем упорядочить код немного более логично, чтобы люди (особенно вы) могли понять, что происходит.

Я обычно избегаю Finder для операций с файловой системой, но в этой ситуации это выгодно, потому что это позволяет один, чтобы сравнить потенциальный список элементов (сгенерированный фильтром whose) с известным списком элементов - что-то, что никакое другое приложение не позволяет (и вместо этого думает, что вы sh сравните его с числом 64). Это также означает, что операция перемещения может быть отменена , если необходимо:

-- Bits of text for joining 
-- Used for the alert dialogs
property lf : linefeed
property lft : linefeed & tab
property lf2 : lf & lf
property lf2t : lf2 & tab
property bullet : "›"
property li : bullet & space

-- Icon files, also used
-- for the alert dialogs
property CoreTypes : "/System/Library/CoreServices/CoreTypes.bundle"
property StopIcon : path to resource "AlertStopIcon.icns" in bundle CoreTypes
property NoteIcon : path to resource "AlertNoteIcon.icns" in bundle CoreTypes


on replace:sender
        set prompt to "Please select some files:"
        set fs to choose file with prompt prompt ¬
                with multiple selections allowed

        -- Get the directory in which the chosen files lie
        set dir to (some item in fs & "::" as text)
        set the text item delimiters to dir's POSIX path

        -- Organise the files into two lists:
        -- PNG files and non-PNG files
        set PNGfs to {}
        repeat with f in fs
                get text items 2 thru -1 of f's POSIX path as text
                set f's contents to the result
                tell f to if its contents ends with ".png" then
                        set end of PNGfs to its contents
                        set its contents to null
                end if
        end repeat
        set fs to every string in fs

        set the text item delimiters to lft & li
        if fs ≠ {} then display dialog ["The following files ", ¬
                "are not PNG files and will be ignored:", lf2t, ¬
                li & fs] as text with title ["Oops…!"] buttons ¬
                ["D'oh!"] with icon NoteIcon default button 1

        if PNGfs = {} then return -- Nothing to move

        tell application id "com.apple.Finder"
                set here to dir as alias -- The source folder
                set there to the (path to the documents folder) -- Destination folder

                -- Enumerate files that might be replaced
                set duplicates to the name of every file ¬
                        in there whose name is in PNGfs

                if duplicates ≠ {} then tell (display dialog contents ¬
                        of ["The following files in ", here's POSIX path, ¬
                        " share names with files in ", there's POSIX path, ¬
                        ":", lf2t & li & duplicates & lf2, "Do you want ", ¬
                        "to:", lft, "• Move all files anyway, replacing ", ¬
                        "the ones in ", there's POSIX path, ";", lft, "•", ¬
                        " Move only the files that can be moved without ", ¬
                        "replacing anything; OR", lft, "• Don't move any", ¬
                        " of the files for now ?"] as text ¬
                        with title ["Replace Existing Files?"] ¬
                        buttons ["Replace", "Keep", "Abort"] ¬
                        default button 1 with icon StopIcon) ¬
                        to set do to its button returned

                -- If the user aborts, the script terminates.
                -- If the user elects to replace existing files, 
                -- then we move those existing files to the trash.
                -- If the user wishes to keep the existing files,
                -- they remain in place.  Either way, the final
                -- operation is the same: move the files without
                -- replacing anything.
                if do = "Abort" then return 0 -- No files moved
                if do = "Replace" then delete ¬
                        (files in there whose ¬
                                name is in ¬
                                duplicates)
                move the (files in here whose ¬
                        name is in PNGfs) to ¬
                        there without replacing
        end tell
end replace:

Делая это таким образом, вы избегаете повторения l oop, и, таким образом, вы получаете только одно диалоговое окно на набор. сгруппированных событий (одно, если пользователь выбирает файлы неправильного типа; другое, если существует риск перезаписи файлов).

На самом деле, вы даже можете избавиться от первого повтора l oop, то есть используется для разделения списка на два типа файлов: команда choose file имеет параметр с именем of type, где вы можете указать один или несколько типов файлов, которые будут ограничены выбором пользователя:

set fs to choose file with prompt prompt ¬
        with multiple selections allowed ¬
        of type ["png"] --OR:["public.png"]

"public.png" - это универсальный идентификатор типа для файлов PNG.

1 голос
/ 05 января 2020

Проще всего добавить флаг, который по умолчанию равен false и установлен на true после того, как пользователь нажмет "Заменить".

Я удалил строку rm, потому что она не нужна, и в любом случае синтаксис неверен.

on replace:sender
    set replaceAll to false
    set allFiles to choose file with prompt "Please select your file:" with multiple selections allowed
    repeat with theFile in allFiles

        tell application "Finder"
            set {name:fileName, name extension:nameExtension, file type:fileType} to theFile
            if fileType is "png" or nameExtension is "png" then
                set myPng to "~/Documents" & fileName as POSIX file
            else
                delay 0.2
                tell current application's NSAlert's alloc's init()
                    (its setMessageText:"Replace Photo")
                    (its setInformativeText:("The file \"" & fileName & "\" is not a PNG file!"))
                    (its setAlertStyle:2)
                    (its setShowsSuppressionButton:false)
                    (its beginSheetModalForWindow:theWindow completionHandler:(missing value))
                    return
                end tell
            end if

            if exists myPng and replaceAll is false then
                delay 0.2
                tell current application
                    display alert "There is already an older item named \"" & fileName & "\" at this location." message ¬
                        "Do you want to replace it with the newer \"" & fileName & "\" one you're moving?" buttons {"Cancel", "Replace"} default button "Replace" as critical

                    set response to button returned of the result
                    if response is "Replace" then
                        delay 0.2
                        do shell script "mv " & quoted form of POSIX path of theFile & space & "~/Documents" with administrator privileges
                        set replaceAll to true
                    end if

                    if response is "Cancel" then
                        return
                    end if
                end tell
            else
                do shell script "mv " & quoted form of POSIX path of theFile & space & "~/Documents" with administrator privileges
            end if
        end tell
    end repeat
end replace:
...