gitとかやるまでもないんだよねー、という場合ありますよね、ないですか。
単に待避フォルダに移動・コピーはAppleScriptでずっとしていたんですが、ちょっとだけ豪華にしました。
適当に待避用フォルダを作成して、ファイルを入れる毎に日時フォルダに分別してコピーまたは移動し、移動の理由も付けておきたいな、という時にもテキストファイルで理由を保存しておけます。
また、複数の待避フォルダがあっても別々に使用したり、一つにマージしたりできます。
これで動作を想像してください。
こんな感じになります。
そのままでもスクリプトエディタやスクリプトメニューから実行できますが、気軽に使うためにはKeyboard Maestroのexecute AppleScriptで実行させましょう。
に待避フォルダ用のiconファイルとscript本体があります。
・icnsファイルは、ホームフォルダのPictures(写真?画像?元からあるものです)に入れてください
・scptは↑のようにスクリプトメニューからでもいいですが、Keyboard Maestroでマクロ作った方が楽しいです
※ほぼChatGPT4oですが、結構な時間かかりました。
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
property targetBaseFolderName : "■待避:"
property searchDepthLimit : 4
property dateTimeFormat : "%y%m%d-%H%M%S"
property reasonFileName : "★待避理由.txt"
property newFolderTagName : "重要"
tell application "Finder"
try
set selectedItems to my getSelectedItems()
set sourceParentFolder to container of item 1 of selectedItems as alias
set sourceParentName to name of sourceParentFolder
if my isInsideTargetFolder(selectedItems, targetBaseFolderName) then
display alert "処理中止" message "選択された項目が「" & targetBaseFolderName & "」フォルダ自体、またはその中にあるようです。" as warning
return
end if
set targetBaseFolder to my findTargetBaseFolder(sourceParentFolder)
if targetBaseFolder is not missing value then
set targetBaseFolderName to name of targetBaseFolder
end if
if targetBaseFolder is missing value then
set userSuffix to my promptForFolderSuffix()
set targetBaseFolderName to targetBaseFolderName & userSuffix
set targetBaseFolder to my findTargetBaseFolder(sourceParentFolder)
if targetBaseFolder is missing value then
set targetBaseFolder to my createTargetBaseFolder(sourceParentFolder)
end if
end if
set {chosenAction, reasonText} to my promptForAction(sourceParentName, targetBaseFolder)
if targetBaseFolder is missing value then
display alert "エラー" message "ターゲットフォルダが見つからず、処理を続行できません。" as critical
return
end if
my ensureFolderTagOverwrite(targetBaseFolder, newFolderTagName)
set subFolder1 to my getOrCreateFolder(targetBaseFolder, sourceParentName)
set dateTimeFolderName to do shell script "date +" & quoted form of dateTimeFormat
set destinationFolder to my createFolder(subFolder1, dateTimeFolderName)
try
if chosenAction is "移動" then
move selectedItems to destinationFolder
else if chosenAction is "コピー" then
duplicate selectedItems to destinationFolder
end if
if reasonText is not "" then my writeReasonFile(destinationFolder, reasonText)
on error errMsg
try
delete destinationFolder
end try
display alert "エラー" message chosenAction & "処理中にエラーが発生しました。" & return & errMsg as critical
end try
end try
end tell
on getSelectedItems()
tell application "Finder"
set selectedList to selection
if selectedList is {} then
display alert "エラー" message "項目が選択されていません。" as critical
error number -128
end if
return selectedList
end tell
end getSelectedItems
on isInsideTargetFolder(targetItems, baseName)
if targetItems is {} then error number -128
tell application "Finder"
set firstSelectedItem to item 1 of targetItems
if name of firstSelectedItem starts with baseName then return true
set checkFolderRef to container of firstSelectedItem
repeat until false
try
if name of checkFolderRef starts with baseName then return true
set checkFolderRef to container of checkFolderRef
on error
exit repeat
end try
end repeat
end tell
return false
end isInsideTargetFolder
on promptForAction(parentFolderName, targetFolder)
set targetFolderName to name of targetFolder
set initialAnswer to (linefeed & linefeed & linefeed & linefeed)
set dialogResult to display dialog "操作を選び、必要なら理由を入力してください:" & return & return & "移動/コピー先:" & return & "「" & targetFolderName & "」>「" & parentFolderName & "」>(日時フォルダ)" default answer initialAnswer buttons {"キャンセル", "コピー", "移動"} default button "移動"
if button returned of dialogResult is "キャンセル" then error number -128
set actionResult to button returned of dialogResult
set reasonResult to text returned of dialogResult
return {actionResult, reasonResult}
end promptForAction
on promptForFolderSuffix()
set suffixDialog to display dialog "待避フォルダがありません。作成しますか?" & return & "これから作成する待避フォルダ名に、テキストを追加できます。" default answer "" buttons {"キャンセル", "作成"} default button "作成"
if button returned of suffixDialog is "キャンセル" then
error number -128
else
return text returned of suffixDialog
end if
end promptForFolderSuffix
on findTargetBaseFolder(startingFolder)
tell application "Finder"
set currentFolderRef to startingFolder
repeat searchDepthLimit times
try
set folderList to folders of currentFolderRef
set foundFolders to {}
repeat with subFolderRef in folderList
if name of subFolderRef starts with targetBaseFolderName then set end of foundFolders to subFolderRef
end repeat
if (count of foundFolders) = 1 then
return item 1 of foundFolders
else if (count of foundFolders) > 1 then
set folderNames to {}
repeat with f in foundFolders
set end of folderNames to name of f
end repeat
set chosenName to my promptFolderSelection(folderNames)
if chosenName is false then return missing value
if class of chosenName is text then
repeat with f in foundFolders
if name of f is chosenName then return f
end repeat
else if class of chosenName is list then
set primaryFolderName to item 1 of chosenName
set primaryFolder to missing value
repeat with f in foundFolders
if name of f is primaryFolderName then
set primaryFolder to f
exit repeat
end if
end repeat
if primaryFolder is missing value then return missing value
repeat with f in foundFolders
set srcPath to POSIX path of (f as alias)
set dstPath to POSIX path of (primaryFolder as alias)
if srcPath is not equal to dstPath then
do shell script "/usr/bin/ditto " & quoted form of srcPath & " " & quoted form of dstPath
delete f
end if
end repeat
return primaryFolder
end if
end if
if class of container of currentFolderRef is desktop folder then exit repeat
set currentFolderRef to container of currentFolderRef
on error errMsg number errNum
if errNum is -128 then
error number -128
else
exit repeat
end if
end try
end repeat
end tell
return missing value
end findTargetBaseFolder
on promptFolderSelection(folderNames)
set chosenFolder to choose from list folderNames with prompt "同一階層に複数の待避フォルダが見つかりました" & return & "使用する待避フォルダを選んでください:" without multiple selections allowed
if chosenFolder is false then error number -128
set selectedName to item 1 of chosenFolder
set confirmDialog to display dialog "選択した待避フォルダ: " & selectedName & return & return & "このフォルダを使用しますか?それとも全ての待避フォルダをこのフォルダにマージしますか?" & return & "※ 同一の時刻のフォルダがある場合は上書きされます" buttons {"キャンセル", "全てマージ", "このフォルダを使用"} default button "このフォルダを使用"
set clickedButton to button returned of confirmDialog
if clickedButton is "キャンセル" then error number -128
if clickedButton is "このフォルダを使用" then return selectedName
if clickedButton is "全てマージ" then return chosenFolder
error number -128
end promptFolderSelection
on createTargetBaseFolder(referenceFolder)
try
set parentFolderRef to container of referenceFolder
on error
set parentFolderRef to referenceFolder
end try
set parentFolderAlias to parentFolderRef as alias
set creationLocationRef to choose folder with prompt "「" & targetBaseFolderName & "」フォルダを作成する場所を選択してください:" default location parentFolderAlias
if creationLocationRef is false then error number -128
tell application "Finder"
set newBaseFolderRef to make new folder at creationLocationRef with properties {name:targetBaseFolderName}
end tell
try
set iconPath to POSIX path of (path to pictures folder) & "hfi.icns"
set imageData to (current application's NSImage's alloc()'s initWithContentsOfFile:iconPath)
(current application's NSWorkspace's sharedWorkspace()'s setIcon:imageData forFile:(POSIX path of (newBaseFolderRef as alias)) options:2)
on error
-- skip icon error
end try
return newBaseFolderRef
end createTargetBaseFolder
on createFolder(parentRef, folderLabel)
if parentRef is missing value or folderLabel is "" then
error number -128
end if
tell application "Finder"
return make new folder at parentRef with properties {name:folderLabel}
end tell
end createFolder
on writeReasonFile(destinationRef, userReasonText)
if destinationRef is missing value then error number -128
try
set trimmedReasonText to do shell script "echo " & quoted form of userReasonText & " | tr -d '[:space:]'"
if trimmedReasonText is "" then return
set reasonFileFullPath to POSIX path of (destinationRef as alias) & reasonFileName
do shell script "echo " & quoted form of userReasonText & " > " & quoted form of reasonFileFullPath
set urlClass to current application's NSURL
set tagKey to current application's NSURLTagNamesKey
set fileURL to urlClass's fileURLWithPath:reasonFileFullPath
fileURL's setResourceValue:{newFolderTagName} forKey:tagKey |error|:(missing value)
on error errMsg
display alert "警告" message "理由ファイルの作成またはタグ付けに失敗しました。" & return & errMsg as warning
end try
end writeReasonFile
on ensureFolderTagOverwrite(targetFolderRef, tagName)
if targetFolderRef is missing value or tagName is "" then error number -128
try
set folderAlias to targetFolderRef as alias
set folderPathText to POSIX path of folderAlias
set folderURL to current application's NSURL's fileURLWithPath:folderPathText
set tagKey to current application's NSURLTagNamesKey
folderURL's setResourceValue:{tagName} forKey:tagKey |error|:(missing value)
on error errMsg
display alert "タグ設定エラー" message errMsg as warning
end try
end ensureFolderTagOverwrite
on getOrCreateFolder(parentRef, childName)
if parentRef is missing value or childName is "" then error number -128
try
set parentAlias to parentRef as alias
tell application "Finder"
try
return folder childName of folder parentAlias
on error
return make new folder at folder parentAlias with properties {name:childName}
end try
end tell
on error errMsg
display alert "フォルダ作成エラー" message errMsg as warning
return missing value
end try
end getOrCreateFolder