めんどうな作業があったのでスクリプトで効率化を試みた。
解決したい課題
- 大量の写真やら動画やら(1000枚くらい)が1つのディレクトリにあって、それを公開用と非公開用に仕分けする
- マウスを使わず、かつ内容を確認してから仕分けたい
- Macで作業する
- iPhotoは重いので使わない
作戦
- 仕分けたいファイル一覧と、仕分け先のディレクトリを得る
- QuickLookで1枚プレビュー
- プレビューしつつキー入力を得て、キーと対応するディレクトリにファイルを移動、プレビューをkillする
- 2,3を繰り返し
プレビュー中に「1」を押すとpublic、「2」を押すとprivateにファイルが移動される、みたいな感じ。
エンターキー押すのはめんどうなので、バッファリングをオフにするため、Cursesを使ってみる。
ソース
#! /usr/bin/ruby -Ku require "curses" require "fileutils" # 特定のディレクトリにあるファイルを複数のディレクトリに分別する # 画像が置いてあるディレクトリを読んで、ファイル一覧を作る if ARGV.size == 0 basedir = Dir.pwd else basedir = ARGV.first end files = Dir.entries(basedir).select{ |f| f.include?('.') }.reject{ |f| f[0..0] == '.'}.map{ |f| File.expand_path(f, basedir) } p files # ファイルの移動先の候補 dirs = [] puts "ファイルを移動する先の候補をスペース区切りで入力してください" puts "(空白の場合,public, privateになります)" print "> " s = $stdin.gets dirs = s.chomp.size > 0 ? s.split(' ') : %w{public private} dirs.map!{ |d| File.expand_path(d, basedir) } dirs.each do |d| if File.directory?(d) puts "#{d}は既に存在します" else puts "#{d}を作りました" Dir.mkdir(d) end end files -= dirs sleep 1 # ファイルを1ずつつプレビューして移動先を聞いていく Curses::init_screen current_num = 0 message_dirs = "" i = 0 dirs.each { |d| message_dirs << "#{i+=1}:#{File.basename(d)} " } message_dirs << "other: don't move" files.each do |file| current_num += 1 Curses::setpos(0, 0) Curses::addstr( "#{current_num} / #{files.size} #{File.basename(file)}" ) Curses::setpos(1, 0) Curses::addstr( message_dirs ) Curses::setpos(2, 0) Curses::addstr( "> " ) # qlmanageで開く # http://ujihisa.nowa.jp/entry/0572683d30 pid = fork { STDERR.reopen(File.open('/dev/null', 'w')) exec ['qlmanage']*2, '-p', file } # 1文字入力を得て(条件によって)移動 str = Curses::getch.chr if str.to_i > 0 and str.to_i <= dirs.size FileUtils.mv(file, dirs[str.to_i-1]) end Process.kill(:TERM, pid) Curses::refresh end # Cursesおわり Curses::close_screen