Sort Files Czy wiesz, że istnieje język skryptowy AutoHotkey (AHK Script), który służy do pisania zautomatyzowany akcji na danym komputerze. Dzięki nie mu możesz na przykład podpiąć daną akcję na skrót klawiszowy. Otwierać swoje ulubione foldery pod F7. Zablokować ALT+F4.
Dodatkowo modyfikować zawartość schowka kopiuj/wklej.
Na przykład modyfikować tekst z tabulatorami tak, aby była to ładna tekstowa tabelka.
Ponownie otworzyć zamknięte wcześniej aplikacje. Automatycznie przerzucać pliki z 1 folderu do drugiego.
AHK Script to potężne narzędzie. Z ciekawości przejrzałem te wszystkie skrypty i wybrałem 1, który rzeczywiście dla mnie jest użyteczny i od ponad 3 miesięcy działa w tle. Może, kiedy przepiszę go na Pythona czy C# na razie AHK Script zdaje egzamin, jeśli chcesz pisać szybko takie skrypty.
Aby pisać skrypty musisz najpierw zainstalować odpowiednie biblioteki ze strony głównej:
Po instalacji każdy plik z rozszerzeniem "ahk" będzie skryptem, który może zostać skompilowany do pliku "exe".
Gdy plik exe uruchomisz będziesz mógł go zobaczyć na pasku narzędzi
Idea jest tak, że potem swój skompilowany skrypt umieszczać do programów startujących wraz z systemem Windows.
Jeśli chodzi o program do pisania skryptów, to może to być notatnik lub Visual Studio Code. Musisz tylko zainstalować te dodatki.
Dadzą ci one kolorowanie składni oraz możliwość debugowania swojego skryptu.
Jak wygląda przykładowy kod ? Oto skrypt, który pod F7 uruchomić ci dany program.
;Launch Sublime Text
F7::Run "C:\Program Files\Sublime Text 2\sublime_text.exe"
return
Oto skrypt, który sprawi, że CAPSLOCK będzie zachowywał się jak SHIFT.
; Caps Lock acts as Shift
Capslock::Shift
return
Oto skrypt, który wyszuka zaznaczony tekst automatycznie w wyszukiwarce Google po wciśnięciu CTRL+SHIFT+C
^+c::
{
Send, ^c
Sleep 50
Run, http://www.google.com/search?q=%clipboard%
Return
}
Oto skrypt, który umieści znak specjalny pod ALT+Q
!q::SendInput {™}
Może chciałbyś automatycznie wpisać swój adres e-mail, gdy napiszesz dwie małyp
::@@::youremail@domain.com
Pora na małą instrukcję jak ustawiać takie klawisze w kodzie:
- ^ to Ctrl
- ! to Alt
- # to Win
- + to Shift
Jak widzisz, bardzo łatwo jest na pisać, nadpisać i stworzyć swoje zachowania klawiszowe.
Myszką też możesz sterować. Oto przykładowy skrypt do sterowania kursorem myszki przy użyciu Num pada:
https://www.autohotkey.com/docs/scripts/NumpadMouse.ahk
Możliwości tutaj się kończą. W teorii możesz zautomatyzować wysłanie e-mail w Outlook-u
HOTKEY:: ; whatever you want it to be
app := ComObjActive("Outlook.Application")
olMailItem := 0
MailItem := app.CreateItem(olMailItem)
MailItem.Subject := "SUBJECT"
;MailItem.Recipient.Add("email@email.com").Type := TO: 1 CC: 2 BCC: 3
MailItem.Recipients.Add("recipientTO@email.com").Type := 1
MailItem.Recipients.Add("recipientCC@email.com").Type := 2
MailItem.Recipients.Add("recipientBCC@email.com").Type := 3
MailItem.Display
Sleep 500
send, BODY TEXT
return
Przejdźmy do króla tego wpisu, czyli do sortowania folderu pobrane w twoim komputerze
Cały skrypt wygląda tak:
;---------------------------------------------------------------------------------------------------------------------------------------;
; Initialization
;---------------------------------------------------------------------------------------------------------------------------------------;
#NoEnv ; Recommended for performance and compatibility with future AutoHotkey releases.
SendMode Input ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir% ; Ensures a consistent starting directory.
#SingleInstance Force
;---------------------------------------------------------------------------------------------------------------------------------------;
; User Variables
;---------------------------------------------------------------------------------------------------------------------------------------;
;Behaviour
MonitoredFolder = D:\PanNiebieski\Pobrane
UnzipTo = D:\PanNiebieski\Pobrane\Compressed
HowOftenToScanInSeconds = 60 ;How long we wait before re-scanning the folder for any changes.
ToolTips = 1 ;Show helper popups showing what the program is doing.
OverWrite = 1 ;Overwrite duplicate files?
RemoveEmptyFolders = 1 ;Delete any folders in the monitored folder that are now empty. (recursive)
;Zip files
7ZipLocation = D:\PanNiebieski\Programy\7-Zip\7zG.exe ;Needed to provide unzipping functionality.
OpenExtractedZip = False ;Open the folder up after extraction has finished?
DeleteZipFileAfterExtract = 1 ;Recycle the zip file after a successful extract.
UnzipSuccessSound = 1 ;Play a jingle when unzipped something.
;What filetypes belong to what group, and what their folder name should be sorted into.
FiletypeObjectArray := [] ;Array needs to be initiated first to work.
PushFiletypeToArray(FiletypeObjectArray,["zip","7z","rar","r00","001"], "Compressed")
PushFiletypeToArray(FiletypeObjectArray,["jpg","bmp","gif","gifv","webm","png","jpeg","swf","tga","tiff","exr","psd"], "Images")
PushFiletypeToArray(FiletypeObjectArray,["txt","nfo","rtf","pdf","docx","doc"], "Documents")
PushFiletypeToArray(FiletypeObjectArray,["xlsm","xlsx","csv"], "Excel")
PushFiletypeToArray(FiletypeObjectArray,["mp3","flac","wav"], "Audio")
PushFiletypeToArray(FiletypeObjectArray,["avi","mpg","mpeg","mov","mp4","mkv","wmv"], "Videos")
PushFiletypeToArray(FiletypeObjectArray,["exe","msi","jar","cmd","bat","ahk"], "Programs")
PushFiletypeToArray(FiletypeObjectArray,["ttf","otf"], "Fonts")
PushFiletypeToArray(FiletypeObjectArray,["h3m"], "Heroes3Maps")
PushFiletypeToArray(FiletypeObjectArray,["tpi"], "TouchPortal")
PushFiletypeToArray(FiletypeObjectArray,["smc"], "SNESGames")
PushFiletypeToArray(FiletypeObjectArray,["adf","lha"], "AmigaGames")
PushFiletypeToArray(FiletypeObjectArray,["vsix"], "VisualStudio Extensions")
;---------------------------------------------------------------------------------------------------------------------------------------;
; Main
;---------------------------------------------------------------------------------------------------------------------------------------;
;Start the folder monitor
WaitTimeBetweenScans := HowOftenToScanInSeconds * 1000
SetTimer, SearchFiles, %WaitTimeBetweenScans%
GoSub,SearchFiles ; Immediately do a scan
return
;---------------------------------------------------------------------------------------------------------------------------------------;
; Functions
;---------------------------------------------------------------------------------------------------------------------------------------;
;Utilities
HasVal(haystack, needle)
{
for index, value in haystack
if (value = needle)
return index
if !IsObject(haystack)
throw Exception("Bad haystack!", -1, haystack)
return 0
}
MakeFolderIfNotExist(TheFolderDir)
{
ifnotexist,%TheFolderDir%
FileCreateDir,%TheFolderDir%
}
RemoveEmptyFolders(Folder)
{
global Tooltips
Loop, %Folder%\*, 2, 1
{
FL := ((FL<>"") ? "`n" : "" ) A_LoopFileFullPath
Sort, FL, R D`n ; Arrange folder-paths inside-out
Loop, Parse, FL, `n
{
FileRemoveDir, %A_LoopField% ; Do not remove the folder unless is empty
If ! ErrorLevel
{
Del := Del+1, RFL := ((RFL<>"") ? "`n" : "" ) A_LoopField
if Tooltips
{
Tooltip,Removing empty folder %FL%
SetTimer, RemoveToolTip, 3000
}
}
}
}
}
return
FindZipFiles(Folder,GoalObjectDestination)
{
global FiletypeObjectArray
global MonitoredFolder
global Tooltips
i = 0
loop % FiletypeObjectArray.Count()
{
i ++
;Get a ref to the object that holds the array of extensions we want.
if FiletypeObjectArray[i].Destination != GoalObjectDestination
continue
o := FiletypeObjectArray[i]
;Unzip
if o ;Without this it may end up unzipping to the root of C drive? i THINK "" defaults to C:\ when using Loop Files
{
Loop, Files, %MonitoredFolder%\*.*,R
{
if HasVal(o.Extensions,A_LoopFileExt)
UnZip(A_LoopFileName,A_LoopFileDir,A_LoopFileFullPath)
}
}
}
}
return
UnZip(FileFullName,Dir,FullPath)
{
global 7ZipLocation ;Saves having to re-pass this dir each time you use this function.
global DeleteZipFileAfterExtract
global OpenExtractedZip
global Tooltips
global UnzipTo
global UnzipSuccessSound
;Get filename
StringGetPos,ExtentPos,FileFullName,.,R
FileName := SubStr(FileFullName,1,ExtentPos)
if Tooltips
{
Tooltip,Unzipping %FileName% > %Dir%\%FileName%
SetTimer, RemoveToolTip, 3000
}
MakeFolderIfNotExist(UnzipTo . "\" . FileName)
Runwait, "%7ZipLocation%" x "%FullPath%" -o"%UnzipTo%\%FileName%"
sleep,2000
IfExist %UnzipTo%\%FileName%
{
if DeleteZipFileAfterExtract
Filerecycle, %FullPath%
if OpenExtractedZip
run, %UnzipTo%\%FileName%
if UnzipSuccessSound
soundplay, *64
}
else
msgbox,,Oh Noes!,Something went wrong and I couldn't unzip %FileName% to %UnzipTo%\%FileName%
}
;Objects
PushFiletypeToArray(InputArray,FiletypesArray,Destination)
{
InputArray.Push(MakeFiletypeObject(FiletypesArray,Destination))
return InputArray
}
MakeFiletypeObject(InputArray,Destination)
{
object := []
object.Extensions := InputArray
object.Destination := Destination
return object
}
GetDestination(TheFile)
{
global FiletypeObjectArray
for i in FiletypeObjectArray
{
if HasVal(FiletypeObjectArray[i].Extensions,A_LoopFileExt)
Destination := FiletypeObjectArray[i].Destination
}
return Destination
}
;---------------------------------------------------------------------------------------------------------------------------------------;
; Subroutines
;---------------------------------------------------------------------------------------------------------------------------------------;
;Main
SearchFiles:
Loop, Files, %MonitoredFolder%\*
{
DestinationFolder := GetDestination(A_LoopFileFullPath)
if (DestinationFolder = "Compressed")
UnZip(A_LoopFileName,A_LoopFileDir,A_LoopFileFullPath)
else if DestinationFolder
{
DestinationFolder := MonitoredFolder . "\" . DestinationFolder
MakeFolderIfNotExist(DestinationFolder)
FileMove,%A_LoopFileFullPath%,%DestinationFolder%\*.*,%OverWrite% ; *.* is needed else it could be renamed to no extension! (If dest folder failed)
if Tooltips
{
Tooltip,Moving %A_LoopFileName% > %DestinationFolder%
SetTimer, RemoveToolTip, 3000
}
}
}
if RemoveEmptyFolders
RemoveEmptyFolders(MonitoredFolder)
FindZipFiles(MonitoredFolder,"Compressed")
;Other
RemoveToolTip:
SetTimer, RemoveToolTip, Off
ToolTip
return
^Esc::ExitApp
W zmiennych określasz zachowanie swojego sortującego programu.
;Behaviour
MonitoredFolder = D:\PanNiebieski\Pobrane
UnzipTo = D:\PanNiebieski\Pobrane\Compressed
HowOftenToScanInSeconds = 60 ;How long we wait before re-scanning the folder for any changes.
ToolTips = 1 ;Show helper popups showing what the program is doing.
OverWrite = 1 ;Overwrite duplicate files?
RemoveEmptyFolders = 1 ;Delete any folders in the monitored folder that are now empty. (recursive)
;Zip files
7ZipLocation = D:\PanNiebieski\Programy\7-Zip\7zG.exe ;Needed to provide unzipping functionality.
OpenExtractedZip = False ;Open the folder up after extraction has finished?
DeleteZipFileAfterExtract = 1 ;Recycle the zip file after a successful extract.
UnzipSuccessSound = 1 ;Play a jingle when unzipped something.
Tutaj określasz jaki folder ma być monitorowany. Gdzie pliki zip mają być wypakowywane. Jak często ma się odbywać skan twojego folderu. Czy plik, które się powtarzają, mają być zastąpione czy nie? Czy puste foldery mają być automatycznie kasowane?
Dodatkowo musi wskazać ścieżkę do programi 7-Zip, który będzie wypakowywał twoje pliki.
Zostało jeszcze określenie czy po wypakowaniu pliku zip automatycznie ma Ci wyskoczyć okno z tym folderem?
Gdy to wiesz, pozostało Ci określić, jakie pliki mają być sortowane gdzie w twoim folderze.
;What filetypes belong to what group, and what their folder name should be sorted into.
FiletypeObjectArray := [] ;Array needs to be initiated first to work.
PushFiletypeToArray(FiletypeObjectArray,["zip","7z","rar","r00","001"], "Compressed")
PushFiletypeToArray(FiletypeObjectArray,["jpg","bmp","gif","gifv","webm","png","jpeg","swf","tga","tiff","exr","psd"], "Images")
PushFiletypeToArray(FiletypeObjectArray,["txt","nfo","rtf","pdf","docx","doc"], "Documents")
PushFiletypeToArray(FiletypeObjectArray,["xlsm","xlsx","csv"], "Excel")
PushFiletypeToArray(FiletypeObjectArray,["mp3","flac","wav"], "Audio")
PushFiletypeToArray(FiletypeObjectArray,["avi","mpg","mpeg","mov","mp4","mkv","wmv"], "Videos")
PushFiletypeToArray(FiletypeObjectArray,["exe","msi","jar","cmd","bat","ahk"], "Programs")
PushFiletypeToArray(FiletypeObjectArray,["ttf","otf"], "Fonts")
PushFiletypeToArray(FiletypeObjectArray,["h3m"], "Heroes3Maps")
PushFiletypeToArray(FiletypeObjectArray,["tpi"], "TouchPortal")
PushFiletypeToArray(FiletypeObjectArray,["smc"], "SNESGames")
PushFiletypeToArray(FiletypeObjectArray,["adf","lha"], "AmigaGames")
PushFiletypeToArray(FiletypeObjectArray,["vsix"], "VisualStudio Extensions")
Według tego kodu pliki:
- "jpg","bmp","gif","gifv","webm","png","jpeg","swf","tga","tiff","exr","psd"
- idą do folderu Images
- "txt","nfo","rtf","pdf","docx","doc"
- idą do folderu Documents
- "xlsm","xlsx","csv"
- idą do folderu Excel
- "mp3","flac","wav"
- idą do folderu Audio
- "avi","mpg","mpeg","mov","mp4","mkv","wmv"
- idą do folderu Video
- "exe","msi","jar","cmd","bat","ahk"
- idą do folderu Programs
Analogicznie możesz dodać swoje foldery do tego automatycznego porządkowania folderu. Jak dodałem rozszerzenie do plików ADF, które są obrazami dyskietek z Amigi. Dodałem także folder do map z Heroes 3.
Jak działa dalej skrypt? Skrypt tak naprawdę raz 60 sekund uruchamia pętle na każdy pliku znajdującym się w folderze.
SearchFiles:
Loop, Files, %MonitoredFolder%\*
{
DestinationFolder := GetDestination(A_LoopFileFullPath)
if (DestinationFolder = "Compressed")
UnZip(A_LoopFileName,A_LoopFileDir,A_LoopFileFullPath)
else if DestinationFolder
{
DestinationFolder := MonitoredFolder . "\" . DestinationFolder
MakeFolderIfNotExist(DestinationFolder)
FileMove,%A_LoopFileFullPath%,%DestinationFolder%\*.*,%OverWrite% ; *.* is needed else it could be renamed to no extension! (If dest folder failed)
if Tooltips
{
Tooltip,Moving %A_LoopFileName% > %DestinationFolder%
SetTimer, RemoveToolTip, 3000
}
}
}
if RemoveEmptyFolders
RemoveEmptyFolders(MonitoredFolder)
FindZipFiles(MonitoredFolder,"Compressed")
;Other
RemoveToolTip:
SetTimer, RemoveToolTip, Off
ToolTip
return
Czy warto mieć taki skrypt uruchomiony? O ile pierwsze uruchomienie było dramatyczne po miałem dużo plików "zip", które nawet nie pamiętam, co trzymały, to później stwierdziłem definitywnie, że ten automatyczny porządek przyspiesza moją pracę.
Wiem, gdzie są obrazki, które przed chwilą ściągnąłem. Wiem, gdzie są instalki, które kiedyś pobrałem.
AHK Script to naprawdę potężne narzędzie i kto wiem, może kiedyś go użyje ponownie.