我在整理數位相片的習慣,一向是依拍照日期分置各自資料夾整理。
數位相機使用頻繁以後,要處理的檔案大增,雖然市面上有許多軟體可以方便做到分資料夾,但是不能完全自訂總是不夠滿意,幸好有PowerShell這個方便的工具,讓我省下許多時間。
以往都是將數位相片在記憶卡中就分好資料夾,並沒有特別變更檔名,但是近來相機數量逐漸增加,而且各大廠四位數序號命名早就拍超過並重新歸零數次,於是前陣子開始再次去閱讀PowerShell的資料,把更名跟分資料夾一次完成。
純粹分置資料夾的指令我愛用了好幾年,一開始是指定位置,我這個"PhotoArrange.ps1"是這樣寫的:
$dir = 'S:\DCIM\102CANON'
cd $dir
$files = dir -path $dir | ?{ !$_.PSIsContainer }
$files | %{ [void] (New-Item -ItemType Directory `
$_.LastWriteTime.ToString("yyyyMMdd") -ErrorAction SilentlyContinue); $_ }`
| %{ Move-Item $_.PSPath -dest $_.LastWriteTime.ToString("yyyyMMdd") }
因為都是在記憶卡就整理,所以單純使用最後修改日期,不去調用EXIF拍照資訊,省得麻煩,缺點是有時候要去改路徑。
後來拍到相機自動新建資料夾,而且多了其他台相機,所以就把目標資料夾路徑去掉,改在桌面捷徑中修改,比較方便。
這個"PhotoArrangeWithoutPath.ps1"是這樣:
$files = dir | ?{ !$_.PSIsContainer }
$files | %{ [void] (New-Item -ItemType Directory `
$_.LastWriteTime.ToString("yyyyMMdd") -ErrorAction SilentlyContinue); $_ }`
| %{ Move-Item $_.PSPath -dest $_.LastWriteTime.ToString("yyyyMMdd") }
然後在桌面的捷徑中,
設定目標為「%SystemRoot%\system32\WindowsPowerShell\v1.0\powershell.exe -noexit D:\路徑\PhotoArrangeWithoutPath.ps1」、
設定開始位置為「S:\DCIM\102CANON」(待整理檔案的路徑位置)。
以上指令所有檔案類型一視同仁都處理,若是讀不到路徑(記憶卡沒插入),會把桌面的所有東西依日期分資料夾擺喔!
題外話,在網路上看到有人把「PsIsContainer」設別名(Alias):
$IsDir = {$_.PsIsContainer}
$IsFile = {!$_.PsIsContainer}
dir | Where $IsDir
dir | Where $IsFile
以避免重複輸入落落長。
重點是聽說PowerShell 第3版有內建:
dir -directory
dir -ad
dir -file
dir -af
這樣真的有比較方便。
回到主題,為了要依照日期變更檔名,想說要做就弄好一點,JPEG檔就去抓EXIF資訊來改,其它檔案再以老方法取修改時間。
本來想用jHead這個以指令惡搞JPEG檔頭資訊的強大好物,搭配PowerShell來整理。
沒想網路上撈到有前人已經以PowerShell寫好了,功能跟我要的幾乎一樣!還加了執行說明畫面,真是棒!
但是小修改還是必須的,我把它的新資料夾路徑從年月改成年月日、加入保留舊檔名及是否使用序號的選項,並把注解及執行畫面都改成中文。
它這個指令調用JamesBrundage的PowerShellPack模組的PSImageTools以讀取EXIF,因為用不到相片EXIF外其他功能,所以另外找了James O'Neill修改自PSImageTools的增強版PowerShell Image模組。
試了一下跟我說有些東西找不到,看來是要先裝PowerShellPack,所以還是乖乖用回PowerShellPack。
這個模組說明要V2以上才能用,WIN7內建的就是囉,雖然執行檔路徑是在1.0,但是在PS畫面下輸入"get-host",可以確認已經是2.0了。
模組服用方式:
安裝前先在PowerShell畫面輸入「$Env:PsModulePath」,看看模組捷徑指向何方,待會要把模組檔放在裡面。
一般放在「%SystemRoot%\system32\WindowsPowerShell\v1.0\Modules\」,則該電腦所有使用者都能使用;
如果沒權限,就去打開「我的文件夾」,放在裡面的「WindowsPowerShell」的「Modules」資料夾裡。
要用的時候,輸入指令「Import-Module 模組名稱」來呼叫模組即可。
上述的PowerShellPack模組是自動安裝檔,會裝在安裝者的"我的文件夾"裡,別的使用者要調用必須自行安裝,或複製一份到system32去大家共用。
安裝好模組後,接下來我的這個"PhotoRenameAndFiling.ps1"指令是這樣寫的:
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# 原作:Rikard Ronnkvist / snowland.se || 修改/中文註解:Tony Huang / tonysnote.blogspot.com
#
# 以下將使用EXIF資訊中的拍照日期,或使用最後修改日期,將JPG及其它檔案更名,並分置於各自子資料夾內。
# 檔案將被更名並放置於:
# \some path\YYYYMMDD\YYYYMMDDHHMMSS_00.JPG
# ^^^^^^^^ - 可選擇是否歸檔,若要則將"createSubdir"設為"True"。
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# 可輸入[$basePath = convert-path ~]選定目前(捷徑設定)路徑,或自設路徑例如:[$basePath = "F:\Pictures\Import dir"]。
$basePath = [Environment]::CurrentDirectory
# $basePath = "F:\Pictures\Import dir"
# 若僅更名不歸檔,可將"$createSubdir"設為"$False"。
$createSubdir = $True
# $createSubdir = $False
# 測試模式,若要測試可將"$testMode"設為"$True"。
$testMode = $False
# $testMode = $True
# 日期時間後保留舊檔名與否。
$keepOldName = $True
# $keepOldName = $False
# 自動加序號與否。
# $addString = $True
$addString = $False
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# 呼叫PowerShellPack模組[http://archive.msdn.microsoft.com/PSImage],為自動安裝檔。
# 若要讓電腦中所有使用者使用,將"我的文件夾\WindowsPowerShell\Modules\"內所有內容,複製到"%SystemRoot%\system32\WindowsPowerShell\v1.0\Modules\"即可。
Import-Module PowerShellPack
# 加上 \* 以搜尋路徑下所有檔案。
$searchPath = $basePath + "\*"
# 搜尋待處理檔案。
Write-Host " 搜尋: " -ForegroundColor DarkGray -NoNewline
Write-Host $basePath -ForegroundColor Yellow
$allFiles = Get-ChildItem -Path $searchPath -Include *.JPG,*.MOV,*.THM,*.RAW,*.AVI -Exclude folder.jpg,*.ini
Write-Host " 找到: " -ForegroundColor DarkGray -NoNewline
Write-Host $allFiles.Count -ForegroundColor Yellow -NoNewline
Write-Host " 個檔案" -ForegroundColor DarkGray
$fNum = 0
# 依序處理所有檔案。
foreach ($file in $allFiles )
{
$fNum++
# 若是jpg檔,使用exif資訊,否則使用最後修改日期。
if ($file.Extension -eq ".JPG") {
$imgInfo = $file | Get-Image | Get-ImageProperty
$fileDate = $imgInfo.dt
} else {
$fileDate = $file.LastWriteTime
}
if ($createSubdir -eq $True) {
# 設定新資料夾路徑。
$fileDir = $basePath + "\" + $fileDate.ToString("yyyyMMdd")
# 檢查新資料夾路徑是否已存在,若無則新建。
if (!(Test-Path($fileDir))) {
# 新建子資料夾路徑。
if ($testMode -ne $True) {
$newDir = New-Item -Type directory -Path $fileDir
Write-Host " 建立: " -ForegroundColor DarkGray -NoNewline
Write-Host $fileDir -ForegroundColor Red
}
}
} else {
# 若檔頭選擇僅更名不歸檔,則將檔案留在目前(捷徑設定)路徑或檔頭自設之路徑,不依日期歸檔。
$fileDir = $basePath
}
# 設定好新的檔名路徑,並於while迴圈開頭時檢查。
$newPath = $file.Fullname
# 若檔頭選擇保留舊檔名,則將其添加於日期時間之後。
if ($keepOldName -eq $True) {
$oldName = "-" + $file.Name.Remove($file.Name.Length - $file.Extension.Length)
} else {
$oldName = ""
}
# 若檔頭選擇添加序號,則添加於主檔名最後。
if ($addString -eq $True) {
$i = 0
while (Test-Path $newPath) {
# 設定有序號之新檔名。
$newPath = $fileDir + "\" + $fileDate.ToString("yyyyMMddHHmmss") + $oldName + "_" + $i.ToString("00") + $file.Extension
$i++
}
} else {
# 設定無序號之新檔名
$newPath = $fileDir + "\" + $fileDate.ToString("yyyyMMddHHmmss") + $oldName + $file.Extension
}
# 顯示執行資訊。
Write-Host $fNum.ToString().PadLeft(4) -ForegroundColor DarkYellow -NoNewline
Write-Host " / " -ForegroundColor DarkGray -NoNewline
Write-Host $allFiles.Count.ToString().PadRight(4) -ForegroundColor Yellow -NoNewline
Write-Host " 移動: " -ForegroundColor DarkGray -NoNewline
Write-Host $file.Name -ForegroundColor Cyan -NoNewline
Write-Host " 到 " -ForegroundColor DarkGray -NoNewline
Write-Host $newPath -ForegroundColor Green
# 更名並移動檔案。
if ($testMode -ne $True) {
Move-Item $file.Fullname $newPath -ErrorAction SilentlyContinue
}
}
使用時一樣在桌面設定好捷徑即可使用,可針對不同相機記憶卡設不同捷徑。
至此大功告成!!
這個網站的部分內容未經考證確認、敘述完全是個人觀點,對此反感者請自行離開,恕不提供謹言慎行版本,或入口網站連結。我有大放厥詞的自由,你有不看的自由,請勿謾罵、歡迎討論~
2012年3月12日 星期一
2012年3月10日 星期六
以前的 Windows PowerShell 筆記
Windows PowerShell 是方便的指令工具,Windows7有內建,較舊的版本也可安裝執行順利,我主要拿來整理照片以及其他檔案。
今天整理資料看到三年前的筆記,貼上來分享一下不專業心得,順便貼一些連結。
================================
下載並安裝PowerShell,PowerShell Help最好也一併下載參考。
在WinXP SP3環境下,安裝路徑在:「%SystemRoot%\system32\WindowsPowerShell\v1.0\」
使用時執行PowerShell「%SystemRoot%\system32\WindowsPowerShell\v1.0\powershell.exe」環境。
輸入「Set-ExecutionPolicy RemoteSigned」以解除近端執行限制,但同時限定遠端腳本須簽署過才能執行。
或者輸入「Set-ExecutionPolicy Unrestricted」以解除所有執行限制。
執行「.ps1」腳本文件時,需提供完整路徑。除非在腳本文件同路徑時,方可以執行「.\example.ps1」代替完整路徑。
若路徑中有空白,須前後加雙引號並以「呼叫運算式」→「&」引用。例如:「& "C:\My Scripts\example.ps1"」。
若在系統「PATH」設定過路徑,則不輸入檔案路徑時,腳本亦可被找到並執行。
若採行此法,為免混淆最好統一集中在同一個資料夾(路徑)中。
可輸入「$a = $env:path; $a.Split(";")」以查詢已設定過之路徑(通常為系統安裝時預設)。
更可輸入「$env:path = $env:path + ";d:\scripts"」,直接把「d:\scripts」這個路徑加進PATH設定最後一行。
"dot sourcing"可將選定腳本的變數及值,存在記憶中並對之後的腳本開放。
例如:假設「. c:\scripts\example.ps1」的內容為:
####[example.ps1] Begin####
$A = 5
$B = 10
$C = $A + $B
####[example.ps1] End####
執行後,再輸入「$C」,可得運算結果「15」。或再執行內容只有「$C」的腳本時,可得到相同結果。
若要清除記憶中的C變數值,可輸入「Remove-Variable C」即可。
不先開啟PowerShell環境,直接執行「powershell.exe –noexit 」後加腳本文件路徑、或腳本內容,可直接獲得運算結果視窗。
若想以此用於登錄腳本,可以以下VBScript呼叫:
####[VBScript that calls PowerShell script] Begin####
Set objShell = CreateObject("Wscript.Shell")
objShell.Run("powershell.exe –noexit c:\scripts\test.ps1")
####[VBScript that calls PowerShell script] End####
================================
PowerShell 在網路上有許多教學資源,其實並不難,尤其是對視窗時代前就開始用電腦的朋友,有時候打指令甚至跑巨集可以解決的東西,比翻來移去,按許多滑鼠按鍵更加方便。
好人賴榮樞大師在微軟TechNet有一系列主筆的專欄,是使用PS必讀的文件:
另外,微軟官方也有許多其他資源:
今天整理資料看到三年前的筆記,貼上來分享一下不專業心得,順便貼一些連結。
================================
下載並安裝PowerShell,PowerShell Help最好也一併下載參考。
在WinXP SP3環境下,安裝路徑在:「%SystemRoot%\system32\WindowsPowerShell\v1.0\」
使用時執行PowerShell「%SystemRoot%\system32\WindowsPowerShell\v1.0\powershell.exe」環境。
輸入「Set-ExecutionPolicy RemoteSigned」以解除近端執行限制,但同時限定遠端腳本須簽署過才能執行。
或者輸入「Set-ExecutionPolicy Unrestricted」以解除所有執行限制。
執行「.ps1」腳本文件時,需提供完整路徑。除非在腳本文件同路徑時,方可以執行「.\example.ps1」代替完整路徑。
若路徑中有空白,須前後加雙引號並以「呼叫運算式」→「&」引用。例如:「& "C:\My Scripts\example.ps1"」。
若在系統「PATH」設定過路徑,則不輸入檔案路徑時,腳本亦可被找到並執行。
若採行此法,為免混淆最好統一集中在同一個資料夾(路徑)中。
可輸入「$a = $env:path; $a.Split(";")」以查詢已設定過之路徑(通常為系統安裝時預設)。
更可輸入「$env:path = $env:path + ";d:\scripts"」,直接把「d:\scripts」這個路徑加進PATH設定最後一行。
"dot sourcing"可將選定腳本的變數及值,存在記憶中並對之後的腳本開放。
例如:假設「. c:\scripts\example.ps1」的內容為:
####[example.ps1] Begin####
$A = 5
$B = 10
$C = $A + $B
####[example.ps1] End####
執行後,再輸入「$C」,可得運算結果「15」。或再執行內容只有「$C」的腳本時,可得到相同結果。
若要清除記憶中的C變數值,可輸入「Remove-Variable C」即可。
不先開啟PowerShell環境,直接執行「powershell.exe –noexit 」後加腳本文件路徑、或腳本內容,可直接獲得運算結果視窗。
若想以此用於登錄腳本,可以以下VBScript呼叫:
####[VBScript that calls PowerShell script] Begin####
Set objShell = CreateObject("Wscript.Shell")
objShell.Run("powershell.exe –noexit c:\scripts\test.ps1")
####[VBScript that calls PowerShell script] End####
================================
PowerShell 在網路上有許多教學資源,其實並不難,尤其是對視窗時代前就開始用電腦的朋友,有時候打指令甚至跑巨集可以解決的東西,比翻來移去,按許多滑鼠按鍵更加方便。
好人賴榮樞大師在微軟TechNet有一系列主筆的專欄,是使用PS必讀的文件:
- Windows PowerShell 講座 (1)—指令、重導、別名
- Windows PowerShell 講座 (2)—自訂工作環境
- Windows PowerShell 講座 (3)— PS 磁碟機
- Windows PowerShell 講座 (4)— 變數
- Windows PowerShell 講座 (5)—儲存資料的其他方式及編寫指令碼的前置準備
- Windows PowerShell 講座 (6)— 運算子(上)
- Windows PowerShell 講座 (7)— 運算子(下)
- Windows PowerShell 講座 (8)— 迴圈與流程控制
- Windows PowerShell 講座 (9)— 模組化
- 易學易用的 Windows PowerShell
- 賴大師擔任板主的微軟技術社群討論區Windows PowerShell板
另外,微軟官方也有許多其他資源:
- 指令碼中心 / 學習園地 的 Windows PowerShell 專頁(中文)
- 線上使用手冊(英文版)
- 依照功能需求分類介紹的教學(簡單的英文):Windows PowerShell Cmdlet 實務指南
- 許多(六千多筆)高手寫好的指令等著你去找來用:Windows PowerShell 範例指令碼存放庫
- 網友TYPE提供的PowerShell 語法說明/範例教學
- 高手 James O'Neill 在MSDN提供的影像EXIF資料存取模組
- Jamesone部落格的PS分類,以及關於上述模組的說明及運用:
- GPS, and other kinds of Picture tagging with PowerShell - 2010/07/01
- Exploring the IMAGE PowerShell Module - 2010/07/05
- Working with the image module for PowerShell; part 3, GPS and other data - 2010/07/07
- 其他一時手邊找沒有,還有很多熱心人士提供過實用教學及範例