#! /bin/sh # ############################################################################# NAME_="cpfound" HTML_="find files and copy" PURPOSE_="recursively find files and copy to a specified dir" SYNOPSIS_="$NAME_ [-vhl] [-i ] -o -p \"\" -s +|-" REQUIRES_="standard GNU commands" VERSION_="1.2" DATE_="2001-10-08; last update: 2006-09-07" AUTHOR_="Dawid Michalczyk " URL_="www.comp.eonworks.com" CATEGORY_="file" PLATFORM_="Linux" SHELL_="bash" DISTRIBUTE_="yes" # ############################################################################# # This program is distributed under the terms of the GNU General Public License # HISTORY: # 2006-09-07 v1.2 - improved the way an integer is appended to files with same # file name. usage () { echo >&2 "$NAME_ $VERSION_ - $PURPOSE_ Usage: $SYNOPSIS_ Requires: $REQUIRES_ Options: -i, , path to where to look for files. Only needed if current dir is not used as input dir. -o, , path to where to copy the found files. In case files with same filenames are found, all copied files have a \"_\" appended incrementally to the prefix where n starts at 1. -s, +|-, file size in bytes; +n for greater then n; -n for less then n; n for exactly n. -p, \"\", search file pattern as accepted by find's -name option; no case distinction is made. -v, verbose -h, usage and options (this help) -l, see this script" exit 1 } # args check [ $# -eq 0 ] && { echo >&2 missing argument, type $NAME_ -h for help; exit 1; } trap "exit 1" 1 2 3 15 # var init file_size= input_dir= output_dir= file_pattern= verbose= while getopts vhli:o:s:p: options; do case "$options" in s) file_size="$OPTARG" ;; i) input_dir="$OPTARG" ;; o) output_dir="$OPTARG" ;; p) file_pattern="$OPTARG" ;; v) verbose=on ;; h) usage ;; l) more $0; exit 1 ;; \?) echo invalid argument, type $NAME_ -h for help; exit 1 ;; esac done shift $(( $OPTIND - 1 )) # args check [[ $file_pattern ]] || { echo >&2 missing file pattern argument; exit 1; } [[ $file_size ]] || { echo >&2 missing file size argument; exit 1; } [[ -d "$output_dir" ]] || { echo >&2 output dir "$output_dir" does not exist; exit 1; } c=1 # local fnc rename_file() { # usage: fnc # keep on checking if file exist; if so, append integer to prefix and check again # Although checking one file at a time starting from 1 may seem like a slow # solution, it's only slow in situations when dealing with huge amounts of # files with same file names. if [ -f "${odir}"/"${prefix}"_${c}."${suffix}" ] ;then ((c++)) rename_file "${prefix}" "${suffix}" # file does not exist; return a valid file name else echo "${prefix}"_${c}."${suffix}" c=1 fi } find_and_cp() { find . -type f -iname "${file_pattern}" -size ${file_size}c | while read a; do file="${a##*/}" prefix="${file%%.*}" suffix="${file#*.}" file_name=$(rename_file "${prefix}" "${suffix}") [[ $verbose ]] && echo ${NAME_}: copying "$a -> ${odir}/${file_name}" cp -- "$a" "${odir}"/"${file_name}" done } # relative and full path support odir=($(cd "$output_dir"; pwd;)) # main if [ $input_dir ];then # relative and full path support idir=($(cd "$input_dir"; pwd;)) [ -d "$idir" ] || { echo >&2 input dir "$idir" does not exist; exit 1; } cd -- "$idir" || { echo >&2 can not cd to "$idir"; exit 1; } find_and_cp else find_and_cp fi