# HG changeset patch # User Edho Arief # Date 1331104671 -25200 # Node ID dd2ddddf00d5fb7f74375c7d78a3c034059c41db # Parent 108e05eb9b5c058cd2aff5ae6bbe958b05d13f19# Parent 4b7b95cb6e09144df7223df6735b7bd4d47c8804 Merge. diff -r 108e05eb9b5c -r dd2ddddf00d5 bin/moefetch --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/bin/moefetch Wed Mar 07 14:17:51 2012 +0700 @@ -0,0 +1,428 @@ +#!/bin/sh + +# Copyright (c) 2009-2012, edogawaconan +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +# +# Lots of bugs here. Use with care +# USE WITH CARE +# +# what it does: fetch every picture that has the specified TAGS. +# requirement: wget, libxslt, openssl + +# program additional paths for: cut, sed, wc, openssl, wget, xsltproc, grep +ADDITIONAL_PATH= + +# default server address. Danbooru only! I do not take responsibility of stupidity. +DEFAULT_SITE="moe.imouto.org" + +# base directory. make sure it's writeable. I do not take responsibility if you don't own the folder and files as no check is done for this one. +# Structure is ${BASE_DIR}/ +# Absolute path only. +# Leave empty to use whatever folder you're running this at +BASE_DIR= + +# not user modifiable from here + +# stop on any error +set -e +# ensures all variables initialized +set -u +useragent="Mozilla/5.0 (Windows NT 6.1; WOW64; rv:10.0) Gecko/20100101 Firefox/10.0" + +# useless welcome message. Also version +msg_welcome() { + echo "moefetch ${_version} +Copyright (c) 2009-2012 edogawaconan +" +} + +# Sanitize path. Totally safe. Usage: cmd "$(safe_path "${filename}")" +safe_path() +{ + # It all depends on the first character. + start=$(printf "%s" "$*" | cut -c 1) + path= + case "${start}" in + .|/) path="$*";; # . and / is safe. No change. + *) path="./$*";; # Anything else must be prefixed with ./ + esac + printf "%s" "${path}" # Return. +} + +# Checks md5. OpenSSL should be available on anything usable. +get_md5() { cat "$(safe_path "${1}")" | openssl dgst -md5 | tail -n 1 | sed -e 's/.*\([[:xdigit:]]\{32\}\).*/\1/'; } + +# Safely get basename. +get_basename() { basename "$(safe_path "${1}")"; } + +# Safely get filename (basename without the extension). +get_filename() { get_basename "${1%.*}"; } + +# Transformation for tag url. +get_cleantags() { printf "%s " "$*" | sed -e 's/\&/%26/g;s/=/%3D/g'; } + +# Returns something if not an md5 value. +is_not_md5() { get_filename "$1" | sed -e 's/\([0-9a-f]\{32\}\)//g'; } + + +# fatal error handler +Err_Fatal() { + echo " +Fatal error: ${1}" + exit 1 +} + +Err_Impossible() { + echo " +Impossible error. Or you modified content of the working directories when the script is running. +Please report to moefetch.googlecode.com if you see this message (complete with entire run log)" + exit 1 +} + +# help message +Err_Help() { + echo "moefetch.sh COMMAND [-n] [-p PASSWORD] [-s SITE_URL] [-u USERNAME] TAGS + +COMMAND: + (quick)fetch: + Do a complete update. Add prefix quick to skip file checking + check: + Get list of new files, clean up local folder and print total new files + +OPTIONS: + -n: + Skip checking repository directory. + -p PASSWORD: + Specifies password for login. + -s SITE_URL: + Specify URL of the Danbooru powered site you want to leech from. Default is ${DEFAULT_SITE}. + -u USERNAME: + Specifies username for login. + TAGS: + Tags you want to download. Separated by spaces. Tag name follows standard Danbooru tagging scheme." + exit 2 +} + +# generate link by transforming xml +Generate_Link() { + echo " +Fetching XML file" + tempnum=1000 + iternum=1 + > "${TEMP_PREFIX}-list" + while [ "${tempnum}" -ge 1000 ]; do + url="http://${SITE}/post/index.xml?tags=$(get_cleantags "${TAGS}")&offset=0&limit=1000&page=${iternum}" + [ ${_use_login} -eq 1 ] && url="${url}&login=${LOGIN_USER}&password_hash=${LOGIN_PASS}" + wget --quiet "${url}" -O "${TEMP_PREFIX}-xml" --referer="http://${SITE}/post" --user-agent="${useragent}" -e continue=off || Err_Fatal "Failed download catalog file" + printf "Processing XML file... " + # xslt evilry + xsltproc - "${TEMP_PREFIX}-xml" < "${TEMP_PREFIX}-templist" + + + + + + +EOF + tempnum=$(grep -c . "${TEMP_PREFIX}-templist") + iternum=$((iternum + 1)) + cat "${TEMP_PREFIX}-templist" >> "${TEMP_PREFIX}-list" + echo "${tempnum} file(s) available" + done + numfiles=$(grep -c . "${TEMP_PREFIX}-list") + echo "${numfiles} file(s) available on server" + [ "${numfiles}" -gt 0 ] || Err_Fatal "Error in processing list or no files can be found with specified tag(s) or site." +} + + +progress_init() { + _last="-" + printf "${_last}" +} + +progress_anim() { + case "${_last}" in + /) _last="-";; + -) _last=\\;; + \\) _last=\|;; + \|) _last="/";; + esac + printf "\b${_last}" +} + +progress_done() { printf "\bdone\n"; } + +# getting rid of ls (as per suggestion) +Count_Files() { + numfiles=0 + for dircontent in "${*}/"* "${*}/".*; do + if [ -e "${dircontent}" ] && [ x"${dircontent}" != x"${*}/." ] && [ x"${dircontent}" != x"${*}/.." ]; then + numfiles=$((numfiles + 1)) + fi + done + echo $((numfiles)) +} + +# check tools availability +Check_Tools() { + # verify all programs required do indeed exist + commands="cut sed wc wget xsltproc xargs rm mkdir chown comm grep date openssl" + for cmd in ${commands} + do + [ "$(command -v "${cmd}")" ] || Err_Fatal "${cmd} doesn't exist in ${PATH}" + done +} + +# verify required folders exist and writeable +Check_Folders(){ + [ -O "${BASE_DIR}" ] || Err_Fatal "You don't own ${BASE_DIR}. Please fix ${BASE_DIR} or run this script in your own directory." + for directory in temp trash deleted "${SITE_DIR}/${TARGET_DIR}"; do + if [ ! -d "${BASE_DIR}/${directory}" ]; then + mkdir -p "${BASE_DIR}/${directory}" || Err_Impossible + fi + if [ ! -O "${BASE_DIR}/${directory}" ]; then + echo "You don't own the ${BASE_DIR}/${directory}, applying globally writeable permission on it" + chmod -R u=rwX,g=rwX,o=rwX "${BASE_DIR}/${directory}" || Err_Impossible + fi + done + [ "$(Count_Files "${BASE_DIR}/${SITE_DIR}/${TARGET_DIR}")" -eq 0 ] && ISNEW=1 + for i in error ok list newlist templist; do + touch "${TEMP_PREFIX}-${i}" || Fatal_Err "Error creating ${TEMP_PREFIX}-${i}. This shouldn't happen" + done + # +} + +# Do some cleanup +Cleanup_Repository() { + # current dir: ${BASE_DIR}/${SITE_DIR}/${TARGET_DIR} + printf "Cleaning up repository folder... " + progress_init + trash_dir="${BASE_DIR}/trash/${trash_dir}/$(date -u "+${SITE_DIR}-${TARGET_DIR}-%Y%m%d-%H.%M")" + trashes="These files have been moved to ${trash_dir}:" + has_trash= + if [ ! -d "${trash_dir}" ]; then + mkdir -p "${trash_dir}" || Err_Impossible + else + if [ ! -O "${trash_dir}" ]; then + chmod -R u=rwX,g=rwX,o=rwX "${BASE_DIR}/${directory}" || Err_Impossible + fi + fi + for trash in "${BASE_DIR}/${SITE_DIR}/${TARGET_DIR}/"* + do + if [ -e "${trash}" ]; then + is_trash= + if [ -d "${trash}" ] || [ -n "$(is_not_md5 "${trash}")" ] || [ -z "$(grep "$(get_basename "${trash}")" "${TEMP_PREFIX}-list")" ]; then + is_trash=1 + has_trash=1 + mv -f -- "${trash}" "${trash_dir}" || Err_Impossible + trashes="${trashes} + $(get_basename "${trash}")" + fi + fi + progress_anim + done + rmdir "${trash_dir}" 2>/dev/null + progress_done + [ -n "${has_trash}" ] && echo "${trashes}" +} + +# check files correctness +Check_Files() { + if [ ! -n "${ISNEW}" ]; then + [ -z "${NOCLEAN}" ] && Cleanup_Repository + printf "Checking for errors... " + progress_init + files_error="These files do not match its md5:" + files_notdanbooru="These files are not checked:" + has_err_filename= + has_err_md5= + > "${TEMP_PREFIX}-error" + > "${TEMP_PREFIX}-ok" + for file in "${BASE_DIR}/${SITE_DIR}/${TARGET_DIR}/"* + do + if [ -e "${file}" ]; then + if [ -n "$(is_not_md5 "${file}")" ] || [ -d "${file}" ]; then + files_notdanbooru="${files_notdanbooru} + $(get_basename "${file}")" + has_err_filename=1 + else + if [ "$(get_md5 "${file}")" = "$(get_filename "${file}")" ]; then + echo "$(get_basename "${file}")" >> "${TEMP_PREFIX}-ok" + else + rm "${file}" || Err_Fatal "Error removing ${file}" + echo "$(get_basename "${file}")" >> "${TEMP_PREFIX}-error" + files_error="${files_error} + $(get_basename "${file}")" + has_err_md5=1 + fi + fi + fi + progress_anim + done + progress_done + if [ ! -n "${has_err_md5}" ] && [ ! -n "${has_err_filename}" ]; then + echo "All files OK" + else + if [ -n "${has_err_md5}" ]; then + echo "${files_error}" + echo "$(grep -c . "${TEMP_PREFIX}-error") file(s) removed" + fi + [ -n "${has_err_filename}" ] && echo "${files_notdanbooru}" + fi + echo "$(grep -c . "${TEMP_PREFIX}-ok") file(s) available locally" + + printf "Generating list of new files... " + progress_init + cp -f "${TEMP_PREFIX}-list" "${TEMP_PREFIX}-templist" + while read -r is_ok; do + grep -v "${is_ok}" "${TEMP_PREFIX}-templist" > "${TEMP_PREFIX}-newlist" + cp -f "${TEMP_PREFIX}-newlist" "${TEMP_PREFIX}-templist" || Err_Impossible + progress_anim + done < "${TEMP_PREFIX}-ok" + progress_done + echo "$(grep -c . "${TEMP_PREFIX}-newlist") file(s) to be downloaded" + else + if [ -n "${ISQUICK}" ]; then + echo "Quick mode selected. Skipping check" + else + echo "Empty local repository" + fi + cat "${TEMP_PREFIX}-list" > "${TEMP_PREFIX}-newlist" + fi +} + +# start downloading the images +Fetch_Images() { + if [ "$(grep -c . "${TEMP_PREFIX}-newlist")" -eq 0 ]; then + echo "No new file" + else + printf "Downloading files... " + cd "${BASE_DIR}/${SITE_DIR}/${TARGET_DIR}" + wget -e continue=on -i "${TEMP_PREFIX}-newlist" -o "${TEMP_PREFIX}.log" --referer="http://${SITE}/post" --user-agent="${useragent}" + fi +} + +# initialize base variables and initial command check +init() +{ + # path initialization + # check if additional path is specified + if [ -n "${ADDITIONAL_PATH}" ] + then + # insert the additional path + PATH="${ADDITIONAL_PATH}:${PATH}" + export PATH + fi + + # misc variables + ISQUICK= + ISNEW= + + # minimum number of arguments: 2 (command and tag). If less than two, exit and print help message + [ $# -lt 2 ] && Err_Help + case "$1" in + check|fetch|quickfetch) + echo "Starting..." + JOB="$1" + ;; + *) + Err_Help + ;; + esac + shift + SITE= + TAGS= + has_pass=0 + has_user=0 + x=1 + while getopts "s:nu:p:" opt + do + case "$opt" in + s) SITE="$OPTARG";; + n) NOCLEAN=1;; + p) + LOGIN_PASS=$(printf "%s" "$OPTARG" | openssl dgst -sha1 | sed -e 's/.*\([[:xdigit:]]\{40\}\).*/\1/') + has_pass=1 + ;; + u) + LOGIN_USER="$OPTARG" + has_user=1 + ;; + esac + x=$OPTIND + done + shift $(($x-1)) + if [ "$1" = -- ]; then shift; fi + TAGS="$@" + [ -n "${SITE}" ] || SITE=${DEFAULT_SITE} + [ -n "${TAGS}" ] || Err_Fatal "No tag specified" + # Get base folder - default, current folder or fallback to ${HOME} + [ -n "${BASE_DIR}" ] || BASE_DIR=${PWD} + [ -n "${BASE_DIR}" ] || BASE_DIR=${HOME} + [ -n "$(echo "${BASE_DIR}" | cut -c1 | grep \/)" ] || BASE_DIR="/${BASE_DIR}" + # see if both pass and use are set. If they're set, switch _use_login variable content to 1. + [ ${has_pass} -eq 1 -a ${has_user} -eq 1 ] && _use_login=1 + + echo "Tags: ${TAGS}" + # slash is not wanted for folder name + TARGET_DIR=$(echo "${TAGS}" | sed -e 's/\//_/g') + SITE_DIR=$(echo "${SITE}" | sed -e 's/\/$//g;s/\//_/g') + TEMP_PREFIX="${BASE_DIR}/temp/${SITE_DIR}-${TARGET_DIR}" +} + +# global variables goes here +init_globals() +{ + _version="1.0-rc3" # version of this script + _use_login=0 # variable to check whether a login is used or not +} + +main() +{ + # removing GNU-ism as much as possible + POSIXLY_CORRECT=1 + #initialize global variables + init_globals + #print welcome message + msg_welcome + # initialization + init "$@" + Check_Tools + Check_Folders + + + # let's do the job! + case "${JOB}" in + check) + Generate_Link + Check_Files + ;; + fetch) + Generate_Link + Check_Files + Fetch_Images + ;; + quickfetch) + ISNEW=1 + ISQUICK=1 + Generate_Link + Check_Files + Fetch_Images + ;; + esac +} + +# call the main routine! +main "$@" + diff -r 108e05eb9b5c -r dd2ddddf00d5 bin/moefetch.sh --- a/bin/moefetch.sh Sun Dec 25 00:50:31 2011 +0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,420 +0,0 @@ -#!/bin/sh - -# Copyright (c) 2009, edogawaconan -# -# Permission to use, copy, modify, and/or distribute this software for any -# purpose with or without fee is hereby granted, provided that the above -# copyright notice and this permission notice appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -# -# Lots of bugs here. Use with care -# USE WITH CARE -# -# what it does: fetch every picture that has the specified TAGS. -# requirement: wget, libxslt, openssl - -# program additional paths for: cut, sed, wc, openssl, wget, xsltproc, grep -ADDITIONAL_PATH= - -# default server address. Danbooru only! I do not take responsibility of stupidity. -DEFAULT_SITE="moe.imouto.org" - -# base directory. make sure it's writeable. I do not take responsibility if you don't own the folder and files as no check is done for this one. -# Structure is ${BASE_DIR}/ -# Absolute path only. -# Leave empty to use whatever folder you're running this at -BASE_DIR= - -# not user modifiable from here - -# useless welcome message. Also version -msg_welcome() { - echo "moefetch ${_version} -Copyright (c) 2009 edogawaconan -" -} - -# Sanitize path. Totally safe. Usage: cmd "$(safe_path "${filename}")" -safe_path() -{ - # It all depends on the first character. - start=$(printf "%s" "$*" | cut -c 1) - path= - case "${start}" in - .|/) path="$*";; # . and / is safe. No change. - *) path="./$*";; # Anything else must be prefixed with ./ - esac - printf "%s" "${path}" # Return. -} - -# Checks md5. OpenSSL should be available on anything usable. -get_md5() { cat "$(safe_path "${1}")" | openssl dgst -md5 | tail -n 1 | sed -e 's/.*\([[:xdigit:]]\{32\}\).*/\1/'; } - -# Safely get basename. -get_basename() { basename "$(safe_path "${1}")"; } - -# Safely get filename (basename without the extension). -get_filename() { get_basename "${1%.*}"; } - -# Transformation for tag url. -get_cleantags() { printf "%s " "$*" | sed -e 's/\&/%26/g;s/=/%3D/g'; } - -# Returns something if not an md5 value. -is_not_md5() { get_filename "$1" | sed -e 's/\([0-9a-f]\{32\}\)//g'; } - - -# fatal error handler -Err_Fatal() { - echo " -Fatal error: ${1}" - exit 1 -} - -Err_Impossible() { - echo " -Impossible error. Or you modified content of the working directories when the script is running. -Please report to moefetch.googlecode.com if you see this message (complete with entire run log)" - exit 1 -} - -# help message -Err_Help() { - echo "moefetch.sh COMMAND [-n] [-p PASSWORD] [-s SITE_URL] [-u USERNAME] TAGS - -COMMAND: - (quick)fetch: - Do a complete update. Add prefix quick to skip file checking - check: - Get list of new files, clean up local folder and print total new files - -OPTIONS: - -n: - Skip checking repository directory. - -p PASSWORD: - Specifies password for login. - -s SITE_URL: - Specify URL of the Danbooru powered site you want to leech from. Default is ${DEFAULT_SITE}. - -u USERNAME: - Specifies username for login. - TAGS: - Tags you want to download. Separated by spaces. Tag name follows standard Danbooru tagging scheme." - exit 2 -} - -# generate link by transforming xml -Generate_Link() { - echo " -Fetching XML file" - tempnum=1000 - iternum=1 - > "${TEMP_PREFIX}-list" - while [ "${tempnum}" -ge 1000 ]; do - url="http://${SITE}/post/index.xml?tags=$(get_cleantags "${TAGS}")&offset=0&limit=1000&page=${iternum}" - [ ${_use_login} -eq 1 ] && url="${url}&login=${LOGIN_USER}&password_hash=${LOGIN_PASS}" - wget --quiet "${url}" -O "${TEMP_PREFIX}-xml" -e continue=off || Err_Fatal "Failed download catalog file" - printf "Processing XML file... " - # xslt evilry - xsltproc - "${TEMP_PREFIX}-xml" < "${TEMP_PREFIX}-templist" - - - - - - -EOF - tempnum=$(grep -c . "${TEMP_PREFIX}-templist") - iternum=$((iternum + 1)) - cat "${TEMP_PREFIX}-templist" >> "${TEMP_PREFIX}-list" - echo "${tempnum} file(s) available" - done - numfiles=$(grep -c . "${TEMP_PREFIX}-list") - echo "${numfiles} file(s) available on server" - [ "${numfiles}" -gt 0 ] || Err_Fatal "Error in processing list or no files can be found with specified tag(s) or site." -} - - -progress_init() { - _last="-" - printf "${_last}" -} - -progress_anim() { - case "${_last}" in - /) _last="-";; - -) _last=\\;; - \\) _last=\|;; - \|) _last="/";; - esac - printf "\b${_last}" -} - -progress_done() { printf "\bdone\n"; } - -# getting rid of ls (as per suggestion) -Count_Files() { - numfiles=0 - for dircontent in "${*}/"* "${*}/".*; do - if [ -e "${dircontent}" ] && [ x"${dircontent}" != x"${*}/." ] && [ x"${dircontent}" != x"${*}/.." ]; then - numfiles=$((numfiles + 1)) - fi - done - echo $((numfiles - 2)) -} - -# check tools availability -Check_Tools() { - # verify all programs required do indeed exist - commands="cut sed wc wget xsltproc xargs rm mkdir chown comm grep date openssl" - for cmd in ${commands} - do - [ "$(command -v "${cmd}")" ] || Err_Fatal "${cmd} doesn't exist in ${PATH}" - done -} - -# verify required folders exist and writeable -Check_Folders(){ - [ -O "${BASE_DIR}" ] || Err_Fatal "You don't own ${BASE_DIR}. Please fix ${BASE_DIR} or run this script in your own directory." - for directory in temp trash deleted "${SITE_DIR}/${TARGET_DIR}"; do - if [ ! -d "${BASE_DIR}/${directory}" ]; then - mkdir -p "${BASE_DIR}/${directory}" || Err_Impossible - fi - if [ ! -O "${BASE_DIR}/${directory}" ]; then - echo "You don't own the ${BASE_DIR}/${directory}, applying globally writeable permission on it" - chmod -R u=rwX,g=rwX,o=rwX "${BASE_DIR}/${directory}" || Err_Impossible - fi - done - [ "$(Count_Files "${BASE_DIR}/${SITE_DIR}/${TARGET_DIR}")" -eq 0 ] && ISNEW=1 - for i in error ok list newlist templist; do - touch "${TEMP_PREFIX}-${i}" || Fatal_Err "Error creating ${TEMP_PREFIX}-${i}. This shouldn't happen" - done - # -} - -# Do some cleanup -Cleanup_Repository() { - # current dir: ${BASE_DIR}/${SITE_DIR}/${TARGET_DIR} - printf "Cleaning up repository folder... " - progress_init - trash_dir="${BASE_DIR}/trash/${trash_dir}/$(date -u "+${SITE_DIR}-${TARGET_DIR}-%Y%m%d-%H.%M")" - trashes="These files have been moved to ${trash_dir}:" - has_trash= - if [ ! -d "${trash_dir}" ]; then - mkdir -p "${trash_dir}" || Err_Impossible - else - if [ ! -O "${trash_dir}" ]; then - chmod -R u=rwX,g=rwX,o=rwX "${BASE_DIR}/${directory}" || Err_Impossible - fi - fi - for trash in "${BASE_DIR}/${SITE_DIR}/${TARGET_DIR}/"* - do - is_trash= - if [ -d "${trash}" ] || [ -n "$(is_not_md5 "${trash}")" ] || [ -z "$(grep "$(get_basename "${trash}")" "${TEMP_PREFIX}-list")" ]; then - is_trash=1 - has_trash=1 - mv -f -- "${trash}" "${trash_dir}" || Err_Impossible - trashes="${trashes} - $(get_basename "${trash}")" - fi - progress_anim - done - rmdir "${trash_dir}" 2>/dev/null - progress_done - [ -n "${has_trash}" ] && echo "${trashes}" -} - -# check files correctness -Check_Files() { - if [ ! -n "${ISNEW}" ]; then - [ -z "${NOCLEAN}" ] && Cleanup_Repository - printf "Checking for errors... " - progress_init - files_error="These files do not match its md5:" - files_notdanbooru="These files are not checked:" - has_err_filename= - has_err_md5= - > "${TEMP_PREFIX}-error" - > "${TEMP_PREFIX}-ok" - for file in "${BASE_DIR}/${SITE_DIR}/${TARGET_DIR}/"* - do - if [ -e "${file}" ]; then - if [ -n "$(is_not_md5 "${file}")" ] || [ -d "${file}" ]; then - files_notdanbooru="${files_notdanbooru} - $(get_basename "${file}")" - has_err_filename=1 - else - if [ "$(get_md5 "${file}")" = "$(get_filename "${file}")" ]; then - echo "$(get_basename "${file}")" >> "${TEMP_PREFIX}-ok" - else - rm "${file}" || Err_Fatal "Error removing ${file}" - echo "$(get_basename "${file}")" >> "${TEMP_PREFIX}-error" - files_error="${files_error} - $(get_basename "${file}")" - has_err_md5=1 - fi - fi - fi - progress_anim - done - progress_done - if [ ! -n "${has_err_md5}" ] && [ ! -n "${has_err_filename}" ]; then - echo "All files OK" - else - if [ -n "${has_err_md5}" ]; then - echo "${files_error}" - echo "$(grep -c . "${TEMP_PREFIX}-error") file(s) removed" - fi - [ -n "${has_err_filename}" ] && echo "${files_notdanbooru}" - fi - echo "$(grep -c . "${TEMP_PREFIX}-ok") file(s) available locally" - - printf "Generating list of new files... " - progress_init - cp -f "${TEMP_PREFIX}-list" "${TEMP_PREFIX}-templist" - while read -r is_ok; do - grep -v "${is_ok}" "${TEMP_PREFIX}-templist" > "${TEMP_PREFIX}-newlist" - cp -f "${TEMP_PREFIX}-newlist" "${TEMP_PREFIX}-templist" || Err_Impossible - progress_anim - done < "${TEMP_PREFIX}-ok" - progress_done - echo "$(grep -c . "${TEMP_PREFIX}-newlist") file(s) to be downloaded" - else - if [ -n "${ISQUICK}" ]; then - echo "Quick mode selected. Skipping check" - else - echo "Empty local repository" - fi - cat "${TEMP_PREFIX}-list" > "${TEMP_PREFIX}-newlist" - fi -} - -# start downloading the images -Fetch_Images() { - if [ "$(grep -c . "${TEMP_PREFIX}-newlist")" -eq 0 ]; then - echo "No new file" - else - printf "Downloading files... " - cd "${BASE_DIR}/${SITE_DIR}/${TARGET_DIR}" - wget -e continue=on -i "${TEMP_PREFIX}-newlist" -o "${TEMP_PREFIX}.log" - fi -} - -# initialize base variables and initial command check -init() -{ - # path initialization - # check if additional path is specified - if [ -n "${ADDITIONAL_PATH}" ] - then - # insert the additional path - PATH="${ADDITIONAL_PATH}:${PATH}" - export PATH - fi - - # misc variables - ISQUICK= - ISNEW= - - # minimum number of arguments: 2 (command and tag). If less than two, exit and print help message - [ $# -lt 2 ] && Err_Help - case "$1" in - check|fetch|quickfetch) - echo "Starting..." - JOB="$1" - ;; - *) - Err_Help - ;; - esac - shift - SITE= - TAGS= - has_pass=0 - has_user=0 - x=1 - while getopts "s:nu:p:" opt - do - case "$opt" in - s) SITE="$OPTARG";; - n) NOCLEAN=1;; - p) - LOGIN_PASS=$(printf "%s" "$OPTARG" | openssl dgst -sha1 | sed -e 's/.*\([[:xdigit:]]\{40\}\).*/\1/') - has_pass=1 - ;; - u) - LOGIN_USER="$OPTARG" - has_user=1 - ;; - esac - x=$OPTIND - done - shift $(($x-1)) - if [ "$1" = -- ]; then shift; fi - TAGS="$@" - [ -n "${SITE}" ] || SITE=${DEFAULT_SITE} - [ -n "${TAGS}" ] || Err_Fatal "No tag specified" - # Get base folder - default, current folder or fallback to ${HOME} - [ -n "${BASE_DIR}" ] || BASE_DIR=${PWD} - [ -n "${BASE_DIR}" ] || BASE_DIR=${HOME} - [ -n "$(echo "${BASE_DIR}" | cut -c1 | grep \/)" ] || BASE_DIR="/${BASE_DIR}" - # see if both pass and use are set. If they're set, switch _use_login variable content to 1. - [ ${has_pass} -eq 1 -a ${has_user} -eq 1 ] && _use_login=1 - - echo "Tags: ${TAGS}" - # slash is not wanted for folder name - TARGET_DIR=$(echo "${TAGS}" | sed -e 's/\//_/g') - SITE_DIR=$(echo "${SITE}" | sed -e 's/\/$//g;s/\//_/g') - TEMP_PREFIX="${BASE_DIR}/temp/${SITE_DIR}-${TARGET_DIR}" -} - -# global variables goes here -init_globals() -{ - _version="1.0-rc2" # version of this script - _use_login=0 # variable to check whether a login is used or not -} - -main() -{ - # removing GNU-ism as much as possible - POSIXLY_CORRECT=1 - #initialize global variables - init_globals - #print welcome message - msg_welcome - # initialization - init "$@" - Check_Tools - Check_Folders - - - # let's do the job! - case "${JOB}" in - check) - Generate_Link - Check_Files - ;; - fetch) - Generate_Link - Check_Files - Fetch_Images - ;; - quickfetch) - ISNEW=1 - ISQUICK=1 - Generate_Link - Check_Files - Fetch_Images - ;; - esac -} - -# call the main routine! -main "$@" - diff -r 108e05eb9b5c -r dd2ddddf00d5 bin/ren --- a/bin/ren Sun Dec 25 00:50:31 2011 +0700 +++ b/bin/ren Wed Mar 07 14:17:51 2012 +0700 @@ -21,6 +21,7 @@ $newname =~ s/\./ /g; $newname =~ s/,([a-z0-9]+)$/.$1/i; } + $newname =~ s/^Gundam Seed (\d+|\d+\[v2\])\.DVD\(H264\.AAC\)\[KAA\]/[KAA] Gundam SEED - $1 [DVD]/i; $newname =~ s/(\[ACX\])(Spiral)( - \d+) - .* (\[[a-f0-9]{8}\]\.mkv)$/$1 $2$3 $4/i; $newname =~ s/^Genesis of Aquarion - (\d+) \[3xR\]\[Blu-ray.720p.H264.FLAC.AC3\](v2|)/[3xR] Genesis of Aquarion - $1 [$2 720p BD]/; $newname =~ s/^Otogi Zoshi Act\.(\d+)\[x264 AAC\]\[SSP-Corp\]/[SSP-Corp] Otogi Zoshi - $1 /; @@ -44,6 +45,8 @@ $newname =~ s/ (Inazuma Eleven - )(\d{2}) / $1 0$2 /; $newname =~ s/\] *Pocket Monsters - (\d+) - .*\[(H264 |)SUB\]/] Pokemon - $1 /i; $newname =~ s/\] Fafner - /] Soukyuu no Fafner - /; + $newname =~ s/\] Inu × Boku SS - /] Inu x Boku SS - /i; + $newname =~ s/\] Inu x Boku Secret Service - /] Inu x Boku SS - /i; $newname =~ s/\] Mashiro iro symphony - /] Mashiro-iro Symphony - /i; $newname =~ s/\] To Aru Kagaku no Railgun /] Toaru Kagaku no Railgun /i; $newname =~ s/\] To Aru Majutsu no Index /] Toaru Majutsu no Index /i; @@ -52,18 +55,28 @@ $newname =~ s/\] Seikon no Qwaser II BD - (\d+) \[720p\]/] Seikon no Qwaser II - $1 [720p BD]/i; $newname =~ s/\] Seikon no Qwaser Picture Drama - (\d+) /] Seikon no Qwaser - Picture Drama $1 /i; $newname =~ s/\] Fortune Arterial Akai Yakusoku - /] Fortune Arterial - /; + $newname =~ s/\] Full Metal Panic Fumoffu - /] Full Metal Panic Fumoffu - /i; $newname =~ s/\[HorribleSubs\] Hunter X Hunter - /[HorribleSubs] Hunter x Hunter (2011) - /i; $newname =~ s/\] Ookami to Koushinryou - /] Spice and Wolf - /; + $newname =~ s/\] Saint Seiya The Lost Canvas - /] Saint Seiya - The Lost Canvas - /; + $newname =~ s/\] Love GetChu - /] Love Get Chu - /i; $newname =~ s/\] Kamen Rider Blade /] Kamen Rider Blade /i; $newname =~ s/\] Mobile Suit Gundam AGE - /] Gundam AGE - /i; $newname =~ s/\] Soredemo Machi wa Mawatte Iru - /] Soredemo Machi wa Mawatteiru - /; $newname =~ s/\] Spiral - (\d+) .* \[640 x 480\]\[H\.264\]/] Spiral - $1 /; - $newname =~ s/\] Mayo Chiki - / ] Mayo Chiki! - /i; + $newname =~ s/\] Mayo Chiki - /] Mayo Chiki! - /i; + $newname =~ s/\] Mai Hime - /] My-HiME - /i; $newname =~ s/\] Naruto Shippuden - /] Naruto Shippuuden - /i; + $newname =~ s/\] -* *Ef - a Tale of Me(l|m)o(d|r)ies - /] ef - a tale of me$1o$2ies /i; $newname =~ s/\] Maji de Watashi ni Koi Shinasai!! /] Maji de Watashi ni Koi Shinasai! /i; $newname =~ s/\] Sei Juushi Bismarck /] Sei Juushi Bismark /i; $newname =~ s/\] Tamayura - hitotose - /] Tamayura ~hitotose~ - /i; $newname =~ s/\] Yumekui Merry /] Dream Eater Merry /i; + $newname =~ s/\] Zero no Tsukaima Final /] Zero no Tsukaima F /i; + $newname =~ s/\] Papa no Iukoto wo Kikinasai! /] Papa no Iu Koto wo Kikinasai! /i; + $newname =~ s/\] Black★Rock Shooter /] Black Rock Shooter /i; + $newname =~ s/\] Mobile Suit Gundam SEED HD Remaster /] Gundam SEED (Remaster) /i; + $newname =~ s/\] *rockman exe axess /] Rockman.EXE Axess /i; $newname =~ s/^Arigatou\.Tsubasa\.Chronicles\.(|2\.)(\d{2})(|v2)\./[Arigatou] Tsubasa Chronicles $1 - $2$3/; $newname =~ s/^Niea\.Under\.Seven\.(\d+)\.\(Dual\.Audio\)\.XVID\.\[AM\]/[AM] Niea Under Seven - $1/; $newname =~ s/ Tsubasa Chronicles 2\. - / Tsubasa Chronicles 2 /; @@ -81,6 +94,8 @@ $newname =~ s/\[WPP & T-N\]/[WPP T-N]/; $newname =~ s/(\[Jumonji-Giri\]) *\[[^]]+\]/$1/i; $newname =~ s/ Yuru Yuri / YuruYuri /i; + $newname =~ s/ Creditless Ending (\d+) ver\. (\d+) / Ending $1.$2 (Clean) /i; + $newname =~ s/ (ef - a tale of me[lm]o[dr]ies) (Ending|Opening) / $1 - $2 /i; $newname =~ s/ Clannad - After Story / Clannad After Story /i; $newname =~ s/ Manyuu Hikenchou - (\d+) ~DC~ / Manyuu Hikenchou - $1 [Uncut]/; $newname =~ s/\[Elysium\]K-ON!!\.EP(\d+)\(BD\.1080p\.FLAC\)/[Elysium] K-ON!! - $1 [1080p BD]/i; @@ -153,6 +168,8 @@ $newname =~ s/ C3 Cube x Cursed x Curious / C3 - Cube x Cursed x Curious /i; $newname =~ s/ Fate( ⁄ | )Zero / Fate-Zero /i; $newname =~ s/ Pollyanna Episode / Pollyanna /; + $newname =~ s/ Ef - A Fairy Tale of the Two / ef - A Fairy Tale of the Two /i; + $newname =~ s/ Ef - A Fairy Tale of the Two-/ ef - A Fairy Tale of the Two -/i; $newname =~ s/^Legend of Galactic Heroes - (\d+) \(([A-F0-9]{8})\) \[Central Anime\]/[Central Anime] Legend of Galactic Heroes - $1 [$2]/; $newname =~ s/\[Hnk\]/[HnK]/; $newname =~ s/^Inuyasha - (\d+|\d+-\d+)\[167\] - .*(\[DVD\]\[AHQ\])/Inuyasha - $1 $2/; @@ -271,23 +288,36 @@ $newname =~ s/ Clean (Opening|Ending) v2/ - $1 (Clean) [v2]/i; $newname =~ s/ Creditless (Opening|Ending) (\d+) / - $1 $2 (Clean) /i; $newname =~ s/ Ep(\d+) Creditless Ending / - Ending $1 (Clean) /i; - $newname =~ s/ (NCED|Ending Clean) / - Ending (Clean) /i; - $newname =~ s/ NCED(\d+) / - Ending $1 (Clean) /i; - $newname =~ s/ (NCOP|Opening Clean) / - Opening (Clean)/i; + $newname =~ s/ (NC-?ED|Ending Clean) / - Ending (Clean) /i; + $newname =~ s/ NC-?ED(\d+) / - Ending $1 (Clean) /i; + $newname =~ s/ (NC-?OP|Opening Clean) / - Opening (Clean)/i; + $newname =~ s/ NC-?OP(\d+) / - Opening $1 (Clean) /i; $newname =~ s/ OP / - Opening /; $newname =~ s/ (\d+-\d+) / - $1 /; $newname =~ s/ - - / - /g; $newname =~ s/ Ep / /ig; ##SLICED BREAD + #v2 $newname =~ s/(\(|\[) *(10bit-v2) *(\)|\])/[v2]/i; - $newname =~ s/(\(|\[) *(h\.264-Hi10P|720x480|10-?bit|10bit 480p H264|640x360|640x360 H264 AAC|h264\.aac|hi10p|10bit|\d+th Release|x264\.aac|xvid|divx5\.2\.1|divx5\.1|divx5\.05|divx5\.1\.1|h\.?264 AC3|848x480|H264 848x480|h264-480p AAC|h\.264-480p) *(\)|\])//i; - $newname =~ s/\[(DVD 10bit)\]/[DVD]/i; - $newname =~ s/(\(|\[) *(DVD H264 640x480|DVD H264 720x480 AAC|DVD 704x480 H264 AC3|DVD 704x480|DVDRip\.Xvid\.864x480\.Vorbis|DVD H264 848x480|DVD 720x480|DVD H264 720x480|DVD, wmv, mp3) *(\)|\])/[DVD]/i; - $newname =~ s/(\(|\[) *(BD\]\[1080p-FLAC|BD 1080|1920x1080 Hi10p h264 AAC|BD 1920x1080 x264 AAC|BD 1080p Hi10P|BDRip 1080p x264 FLAC|BD-1080p-|BD-1080p-FLAC|1920x1038 Blu-Ray FLAC|1920x1080 Blu-Ray FLAC|1920x1080 h264 BD FLAC|1920x1080 BD|BD\.1080p\.FLAC|BD 1080p H\.264 AAC 5\.1|BD 1080p) *(\)|\])/[1080p BD]/i; - $newname =~ s/(\(|\[) *(Hi10P 1280x720 H264|Hi10P 1280x720|1280x720 Hi10P|1280x720 5\.1|1280x720 x264 AAC|1280x720 H264 AAC|720p H264 AAC|1280x720|1280x720 H\.?264 AAC) *(\)|\])/[720p]/i; - $newname =~ s/(\(|\[) *(BD, 720, 10bit, AAC|BDrip 720p Vorbis|BD 720p Hi10P AAC|BD, 720p,|BD 720p H264-AAC|BDRip 720p|BD, 720p, ,|1280x720 BD|BD 1280x720 H264 AAC|BD 720p|BD 720p FLAC|BD 1280x720 H264 AAC) *(\)|\])/[720p BD]/i; - $newname =~ s/(\(|\[) *(BD 540p) *(\)|\])/[BD]/i; + #dvd v2 + $newname =~ s/ \[DVD\] v2/ [v2 DVD]/i; + #nothing + $newname =~ s/(\(|\[) *(H264 704x400|640x480 DivX511 120fps mp3|640x480 DivX511 mp3|h\.264-Hi10P|720x480|10-?bit|10bit 480p H264|640x360|640x360 H264 AAC|h264\.aac|hi10p|10bit|\d+th Release|x264\.aac|xvid|divx5\.2\.1|divx5\.1|divx5\.05|divx5\.1\.1|h\.?264 AC3|848x480|H264 848x480|h264-480p AAC|h\.264-480p) *(\)|\])//i; + #dvd + $newname =~ s/(\(|\[) *(DVD-480p-AAC|DVD x264 10-bit AC3|DVD 10bit) *(\)|\])/[DVD]/i; + #dvd again + $newname =~ s/(\(|\[) *(R2 DVD\.H264\.AC3|DVD H264 720x480|DVD 720x480 x264 FLAC|R1DVD 720x480 x264 AC-3|DVD 712x480 AC-3|DVD 720x480 AC-3|R\d DVD\.H264\.AC3|DVD 1024x576 x264 FLAC|DVD H264 640x480|DVD H264 720x480 AAC|DVD 704x480 H264 AC3|DVD 704x480|DVDRip\.Xvid\.864x480\.Vorbis|DVD H264 848x480|DVD 720x480|DVD H264 720x480|DVD, wmv, mp3) *(\)|\])/[DVD]/i; + #1080p BD + $newname =~ s/(\(|\[) *(BDRip 1080p x264 FLAC|BD Hi10P 1920x1080|BD Hi10P 1920x1080 H264 FLAC|BD 1920x1080 x264 Hi10P FLAC|BD 1920x1080 Hi10P|1920x1080 BD AAC|BD\]\[h264-1080p FLAC|BD-h264-10bit-1080p|BD\]\[1080p-FLAC|BD 1080|1920x1080 Hi10p h264 AAC|BD 1920x1080 x264 AAC|BD 1080p Hi10P|BDRip 1080p x264 FLAC|BD-1080p-|BD-1080p-FLAC|1920x1038 Blu-Ray FLAC|1920x1080 Blu-Ray FLAC|1920x1080 h264 BD FLAC|1920x1080 BD|BD\.1080p\.FLAC|BD 1080p H\.264 AAC 5\.1|BD 1080p) *(\)|\])/[1080p BD]/i; + #720p + $newname =~ s/(\(|\[) *(1280x720 Hi10p|AT-X Hi10P 1280x720|1280x720 Hi10p AAC|AT-X 1280x720 H264|Hi10P 1280x720 H264|Hi10P 1280x720|1280x720 Hi10P|1280x720 5\.1|1280x720 x264 AAC|1280x720 H264 AAC|720p H264 AAC|1280x720|1280x720 H\.?264 AAC) *(\)|\])/[720p]/i; + #720p BD + $newname =~ s/(\(|\[) *(BD, 720p, 10bit, AAC|BDRip 720p x264 FLAC|BDRip 720p|BD 720p DA|Blu-Ray 960x720 Dual Audio FLAC|BD, 720p|BD\]\[h264-720p\]\[FLAC|BD Hi10P 1280x720|BD, 720p, 10bit,|BD, 720, 10bit, AAC|BDrip 720p Vorbis|BD 720p Hi10P AAC|BD, 720p,|BD 720p H264-AAC|BDRip 720p|BD, 720p, ,|1280x720 BD|BD 1280x720 H264 AAC|BD 720p|BD 720p FLAC|BD 1280x720 H264 AAC) *(\)|\])/[720p BD]/i; + #BD + $newname =~ s/(\(|\[) *(Blu-Ray|BD 540p) *(\)|\])/[BD]/i; + #576p $newname =~ s/(\(|\[) *(1024x576|H264 1024x576) *(\)|\])/[576p]/i; + #1080p $newname =~ s/(\(|\[) *(1920x1080) *(\)|\])/[1080p]/i; ##SLICED BREAD pt.2 $newname =~ s/(\d+)v(\d+)/$1 [v$2]/i; @@ -460,7 +490,11 @@ $newname =~ s/ The World God Only Knows - 2 - / The World God Only Knows 2 - /; $newname =~ s/ Legend of Galactic Heroes Gaiden - 2 - / Legend of Galactic Heroes Gaiden 2 - /; $newname =~ s/ Kara no Kyoukai - (\d+) / Kara no Kyoukai - Chapter $1/; + $newname =~ s/ Persona - 4 The Animation / Persona 4 - /; + $newname =~ s/ Persona - 4 / Persona 4 - /; $newname =~ s/\[G P\]/[G_P]/i; + $newname =~ s/\[-'\]/[-__-']/; + $newname =~ s/\['\]/[-__-']/; #SAFE CLEANUPS $newname =~ s/ +/ /g; $newname =~ s/^ +//; @@ -472,6 +506,7 @@ $newname =~ s/^Naruto - (\d{2}) /Naruto - 0$1 /; $newname =~ s/^Fairy Tail - (\d{2}) /Fairy Tail - 0$1 /; $newname =~ s/^Naruto - (\d{2})-(\d{2}) /Naruto - 0$1-0$2 /; + $newname =~ s/\[(v\d+)\]\[(DVD)\]/[$1 $2]/i; if ($^O eq "MSWin32") { $newname =~ s/ *\\ */\\/g; } print(qq($_: $newname already exists, skipping\n)) and next() if -e $newname and $_ ne $newname; if ($_ eq $newname) { diff -r 108e05eb9b5c -r dd2ddddf00d5 bin/startssl-nginx --- a/bin/startssl-nginx Sun Dec 25 00:50:31 2011 +0700 +++ b/bin/startssl-nginx Wed Mar 07 14:17:51 2012 +0700 @@ -7,9 +7,9 @@ certfile="${1}" -command -v curl 2> /dev/null || _err_fatal "This script requires cURL. Please install it first." +command -v curl 2>&1 > /dev/null || _err_fatal "This script requires cURL. Please install it first." test -z "${certfile}" && _err_fatal "Please specify certificate file." -test -f "${certfile}" && _err_fatal "Error reading certificate file ${certfile}." +test -f "${certfile}" || _err_fatal "Error reading certificate file ${certfile}." for ca in sub.class1.server.ca.pem ca.pem; do curl "http://www.startssl.com/certs/${ca}" >> "${certfile}" diff -r 108e05eb9b5c -r dd2ddddf00d5 rc/bash --- a/rc/bash Sun Dec 25 00:50:31 2011 +0700 +++ b/rc/bash Wed Mar 07 14:17:51 2012 +0700 @@ -26,10 +26,13 @@ export LANG="en_US.UTF-8" export CLICOLOR= export LSCOLORS=ExGxFxdxCxegedabagExEx +export LS_COLORS= +export BLOCKSIZE=1K +export BLOCK_SIZE=si alias ls="ls -F" alias rm="rm -i" -alias rd="rdesktop -g 1280x600 -K -a 16 -z -P -r sound:off -r clipboard:CLIPBOARD -5" +alias rd="rdesktop -g 1280x600 -K -a 15 -x m -z -P -r sound:off -r clipboard:CLIPBOARD -5" _has_gnu_ls= _has_gnu_grep= @@ -122,6 +125,10 @@ for i in {"${HOME}/app","/opt"}/{tmux,ruby19,node,tarsnap,symon,nginx}/{bin,sbin}; do [ -d "${i}" ] && PATH="${i}:${PATH}" done +# New(?) rubygems bin PATH +for i in {"${HOME}/app","/opt"}/ruby19/lib/ruby/gems/1.9.1/bin; do + [ -d "${i}" ] && PATH="${i}:${PATH}" +done # MySQL in common locations highest priority since new = better. Also no compatibility problem. # Cluster is superset of Enterprise/GPL so it gets highest priority. @@ -174,4 +181,3 @@ rm -If "/tmp/.nonexistent.$(date '+%Y%m%d%H%M%S')" 2> /dev/null && alias rm="rm -I" [ -f "${HOME}/.ecos_bash.after" ] && . "${HOME}/.ecos_bash.after" - diff -r 108e05eb9b5c -r dd2ddddf00d5 rc/hg --- a/rc/hg Sun Dec 25 00:50:31 2011 +0700 +++ b/rc/hg Wed Mar 07 14:17:51 2012 +0700 @@ -10,9 +10,10 @@ [extensions] #hgext.convert = #progress = +hgext.bookmarks = [hostfingerprints] -bitbucket.org = 81:2b:08:90:dc:d3:71:ee:e0:7c:b4:75:ce:9b:6c:48:94:56:a1:fe +bitbucket.org = 24:9c:45:8b:9c:aa:ba:55:4e:01:6d:58:ff:e4:28:7d:2a:14:ae:3b [defaults] addremove = --similarity 100 diff -r 108e05eb9b5c -r dd2ddddf00d5 rc/inputrc --- a/rc/inputrc Sun Dec 25 00:50:31 2011 +0700 +++ b/rc/inputrc Wed Mar 07 14:17:51 2012 +0700 @@ -30,4 +30,4 @@ #Misc "\C-w": unix-filename-rubout - +"\C-d": complete