初歩のシェルスクリプトで遊ぶ[ファイルのリネームツール、のようなもの?_(1)]
名前は「burdock」
シェルスクリプトでファイルのリネームツールを作って……作れたのかなぁ。リネームできてるっちゃあできてますが、画像の形式変換だとかもできちゃうんすけど……。
使用例
1.写真ファイルからexif情報を取り出してリネーム_端末用インターフェースから
(途中でテキストファイルを編集する必要あり)
- UIのプラグインスクリプトでImageMagickを実行、EXIF情報をテキストファイルに書き出し、
- 別の任意のツールでテキストファイルを編集してから、
2.ファイルに乱数のサフックスをつけてリネーム_コマンドラインから
- シェル変数モードに変更し、
- コマンド実行モードを1ファイル1実行モードに切り替え、
- サフックスにBash組み込み変数の${RANDOM}を、1ファイルにつき1回展開しながら付加する。
$ ls | burdock --shell --once '_suffix "_${RANDOM}"' cd -- "/media/sf_003" ; mv -n -v -- 'diary.txt' 'diary_30078.txt' ; cd -- "/media/sf_003" ; mv -n -v -- 'image.jpg' 'image_3938.jpg' ; cd -- "/media/sf_003" ; mv -n -v -- 'memo.txt' 'memo_13931.txt' ; cd -- "/media/sf_003" ; mv -n -v -- 'picture.jpg' 'picture_9382.jpg' ;
コマンドライン版の中核スクリプトのみ
と、けっこう量があるんで、どうやるべかと。
プログラマーの世界だと常識な方法とかあるんでしょうけど、私にゃ分からんので、あとでzipで出します。フォントと同じところにでも。
スクリプト1枚で動く中核部分だけ置いときます。もう基本仕様は変わらんと思うから。
ユーザインターフェースのほうは、まだ書き換えが激しくて。公開してもすぐ消しちゃいそうなんす。
#!/bin/bash #set -x # ========================================================================================== # ■ ファイルリネーム 「burdock」Core ver8 # ========================================================================================== # ---- 許可リスト_ユーザ設定 (うっかりミス防止) ------------------------------------- # 任意コマンド実行時、「${ARROW_LIST_CMD[]}」に # 明記されたコマンドが先頭に有るときのみ実行を許可する。 # 「_」は組み込みシェル変数とスクリプト用 # 全てのコマンドを許可するなら、「.」を追加する declare -a -g ARROW_LIST_CMD ARROW_LIST_CMD=( _ sed tr cut xargs echo printf rev awk date nl iconv nkf ) # ==== 前処理開始 ========================================================================= # 【debug】動作速度測定 SECONDS=0 : '【PATH追加】' && { SCRIPT_DIR=`dirname $( readlink --canonicalize-existing "${0}" )` PATH="${SCRIPT_DIR}:${SCRIPT_DIR}/burdockCoreLib:${PATH}" if ! . coreLib.func ; then echo "${0}:組み込みコマンドは無効です。" 1>&2 fi } : '【フラグ初期化】' && { # 一度trueにすると、falseには戻らない stdinFlag='false' demoFlag='false' actionFlag='false' pipeFullFlag='false' pipeNameFlag='false' pipeExtFlag='false' pipeCsvFlag='false' arrowlistFlag='false' cmdAnalysFlag='false' cmdAnalysFullFlag='false' databaseFlag='false' } : '【スイッチ初期値】' && { # オプションで切り替わる。命令が無い限り状態を保持する。 # CMD_TARGET を設定 cmdTargetSW='name' #cmdTargetSW='ext' # CMD_ACTION を設定 #cmdActionSW='once' cmdActionSW='loop' # CMD_VAR_MODE を設定 databaseSW='escape' #databaseSW='database' #databaseSW='shell' } : '【stdinは入力されたか?】' && { if test -p /dev/stdin ; then stdinFlag='true' else true fi } : '【位置パラメータ取得用_シェル関数】' && { fileLoadFunc(){ # ユーザ指定ファイルを読み込む # ${1} ファイルパス 指定変数名はファイル名をそのまま使う local loadFilePath loadFileName NN XX # 【ザル】 # プロセス置換、通常ファイル、オプション、で分岐 if test -p "${1}" ; then echo "${0}:${1}:パイプファイルを検出しましたが、使用できません。通常のファイルからの読み込みにのみ対応します。" 1>&2 exit 0 elif test -f "${1}" ; then true else return 1 fi loadFilePath=`readlink --canonicalize-existing "${1}"` loadFileName="${loadFilePath##*/}" NN='-1' while read -r XX ; do NN=$(( ${NN} + 1 )) DATA_BASE[${loadFileName}_${NN}]="${XX}" done 0< "${loadFilePath}" DATA_BASE[${loadFileName}]="${DATA_BASE[${loadFileName}_0]}" return 0 } } : '【位置パラメータ・同等ファイル_取得用_配列宣言】' && { # 入力された生データをリニアに並べて整理する declare -a -g POSITION_PARM # ---- リネームコマンドとそのプロパティ1次配列 ---------------------- # ファイル名・拡張子変換リネームコマンド 統合配列 declare -a -g CMD_1D # 「loop once」「name ext」適用対象は名前か拡張子か declare -a -g CMD_ACTION CMD_TARGET # 「escape database shell」シェル変数の扱い_$=>\\$,DATA_BASE,無変換 declare -a -g CMD_VAR_MODE # ---- その他_連想配列 ------------------------------------------------ # # ファイル名・拡張子変換 統合配列 x ファイル数 declare -A -g CMD_2D # データベース_内部作成,外部ファイルLoad declare -A -g DATA_BASE } : '【位置パラメータとリネームコマンドファイルを線形取得】' && { # 位置パラメータを配列に読み込む。 # 位置パラメータで指定された、リネームコマンドファイルも読み込む。 # これらを順に配列に格納し、連続したパラメータに整理する。 while test ${#} -ne 0 ; do # ----------------------------------------↓ case "${1}" in ( --loadcmd | --loadcommand ) # ファイルから読み込み if test -e "${2}" ; then shift 1 else echo "ERR:${2}:存在しません" exit 2 fi # txt行を配列に格納(空行を詰めながら) while read -r LL ; do if test -n "${LL}" ; then POSITION_PARM+=("${LL}") fi done 0< "${1}" ;; ( * ) # 位置パラメータのファイルload以外すべてを配列に格納 POSITION_PARM+=("${1}") ;; esac shift 1 done # ---------------------------------------------------------------↑ : << '#------------------------------debug' ( IFS=' ' ; echo "${POSITION_PARM[*]}" 1>&2 ) #------------------------------debug } : '【位置パラメータ取得】' && { NN='0' while test ${NN} -lt "${#POSITION_PARM[@]}" ; do # ------------------------------↓ case "${POSITION_PARM[${NN}]}" in # ---- コマンド適用対象を切り替え ---------------------------------------- ( --name ) # 名前にコマンドを適用する cmdTargetSW='name' ;; ( --ext ) # 拡張子にコマンドを適用する cmdTargetSW='ext' ;; # --- コマンド実行タイプを切り替え --------------------------------------- ( --loop ) # まとめて1度の実行 cmdActionSW='loop' ;; ( --once ) # 1回の処理で1度実行 cmdActionSW='once' ;; # ---- データベース ---------------------------------------------------- ( --escape ) databaseSW='escape' ;; ( --database ) # シェル変数モードON(true)/OFF(false) databaseSW='database' databaseFlag='true' ;; ( --shell ) databaseSW='shell' ;; ( --data-load | --database-load ) # ファイルを読み込んで${DATA_BASE[]}を作成 while fileLoadFunc "${POSITION_PARM[${NN}+1]}" ; do NN=$(( ${NN} + 1 )) databaseFlag='true' done ;; # ---- 実行モード指定 -------------------------------------------------- ( --action ) # リネーム実行 actionFlag='true' ;; ( --demo ) # リネーム実行予想_mvコマンドを出力 demoFlag='true' ;; ( --pipe-full ) # 変更予定ファイル名のみをフルパス表示 pipeFullFlag='true' ;; ( --pipe-name ) # パスを除く名前のみを出力 pipeNameFlag='true' ;; ( --pipe-ext ) # パスを除く拡張子のみを出力 pipeExtFlag='true' ;; ( --pipe-csv ) pipeCsvFlag='true' ;; # ---- 許可リストを出力 -------------------------------------------- ( --arrowlist ) arrowlistFlag='true' ;; # ---- コマンドのみの解析結果(入力ファイルと無関係な解析)を出力 -------- ( --cmd-analysis ) cmdAnalysFlag='true' ;; # ---- 入力ファイル数に従って作成したコマンドを出力する ---------------- ( --cmd-analysis-full ) cmdAnalysFullFlag='true' ;; # ---- etc -------------------------------------------------------------- ( -- ) # 以降の引数を無視する break ;; # ---- リネームコマンドを格納 ------------------------------------------ ( * ) # 上記オプション以外は、すべてリネームコマンド1単位と見なす CMD_1D+=("${POSITION_PARM[${NN}]}") CMD_TARGET+=(${cmdTargetSW}) CMD_VAR_MODE+=(${databaseSW}) CMD_ACTION+=(${cmdActionSW}) ;; esac NN=$(( ${NN} + 1 )) done # ----------------------------------------------------------------------------↑ : '【コマンドリスト簡易チェック】' && { if test "${#CMD_1D[@]}" -eq "${#CMD_ACTION[@]}" && test "${#CMD_1D[@]}" -eq "${#CMD_TARGET[@]}" && test "${#CMD_1D[@]}" -eq "${#CMD_VAR_MODE[@]}" ; then true else echo 'コマンドリスト受け取りでエラー' 1>&2 ; exit 2 fi } } : '【動作モード判定1】' && { # ---- Mode判定1 -------------------------------------------------------------- if test ${arrowlistFlag} = 'true' ; then # (1) 許可リスト出力 Mode='arrowlist' elif test ${cmdAnalysFlag} = 'true' ; then # (2) コマンドのみ解析 Mode='cmdAnalys' elif test ${stdinFlag} = 'false' ; then # (3) 簡易説明書 Mode='usage' elif test ${stdinFlag} = 'true' ; then # (4) 各種メインプロセス実行へ Mode='mainproc' else echo '想定外のエラー' 1>&2 exit 2 fi # (1) 許可リスト出力 -> exit # (3) usage -> exit case "${Mode}" in ( arrowlist ) echo ${ARROW_LIST_CMD[@]} exit 0 ;; ( usage ) echo 'ls | '"${0}"' command ....' exit 0 ;; esac } : '【疑わしいコマンドを検査】' && { # 検査用grepコマンドの引数を作成 XX=`echo "${ARROW_LIST_CMD[@]}" | sed -e 's/[^ ]*/-e ^&/g'` # echo "${XX}" 1>&2 # 【debug】 # (2) コマンド解析 -> exit # (4) 各種メインプロセス実行前_コマンド解析 case "${Mode}" in # ---------------------------------------------------------------- ( cmdAnalys ) # コマンド単独の詳細検査 --> exit # ---------------------------------------------------------------- exitCode='0' NN='0' # コマンド単独の詳細検査_表示 for NN in "${!CMD_1D[@]}" ; do # CMD_1Dが空のときはNNをリセットできない YY=`echo "${CMD_1D[${NN}]}" | grep --invert-match ${XX}` if test -z "${YY}" ; then # 許可リスト通過分 echo ${NN}' '"${CMD_TARGET[NN]}"' '"${CMD_ACTION[NN]}"' '"${CMD_VAR_MODE[NN]}"' '"pass"' '"${CMD_1D[NN]}" else echo ${NN}' '"${CMD_TARGET[NN]}"' '"${CMD_ACTION[NN]}"' '"${CMD_VAR_MODE[NN]}"' '"block"' '"${CMD_1D[NN]}" exitCode='1' fi done echo "${#CMD_1D[@]}"' '${cmdTargetSW}' '${cmdActionSW}' '${databaseSW}' '"--"' '"NEXT" # 判定用_終了コード exit ${exitCode} ;; # ---------------------------------------------------------------- ( mainproc | * ) # 簡易検査 --> 合格した場合はメイン処理へ # ---------------------------------------------------------------- YY=`for NN in ${!CMD_1D[@]} ; do echo "${CMD_1D[${NN}]}" done | grep --invert-match ${XX}` # echo "${YY}" 1>&2 # 【debug】 if test -z "${YY}" ; then # **** 合格 メイン処理を実行する ************************ true else echo "${YY}" | sed -e 's/^/ERR_入力禁止:/' | xargs -I '{}' printf '\033[1;31;40m%s\033[0m\n' '{}' 1>&2 exit 1 fi ;; esac } # :::: 各種メイン処理実行が決定 ::::::::::::::::::::::::::::::::::::::::::::::::::: : '【動作モード判定_メイン処理を分岐】' && { # リネームコマンドが完成次第stderrへ出力して終了する if test ${cmdAnalysFullFlag} = 'true' ; then Mode='renameCommandFull' # demoモード明示 mvコマンドを出力する elif test ${demoFlag} = 'true' ; then Mode='mvCommand' # pipeモード 出力ファイル名のみを絶対パス出力する elif test ${pipeFullFlag} = 'true' ; then Mode='pipeFull' elif test ${pipeNameFlag} = 'true' && test ${pipeExtFlag} = 'true' ; then # パス無しの名前と拡張子を出力 Mode='pipeNameExt' elif test ${pipeNameFlag} = 'true' && test ${pipeExtFlag} = 'false' ; then # パス無しの名前を出力 Mode='pipeName' elif test ${pipeNameFlag} = 'false' && test ${pipeExtFlag} = 'true' ; then # パス無しの拡張子を出力 Mode='pipeExt' # actionを明示されたときのみmvコマンド実行 elif test ${actionFlag} = 'true' ; then Mode='Action' elif test ${pipeCsvFlag} = 'true' ; then Mode='Csv' # stdinが有っただけならばmvコマンドの文字列を出力し、mvコマンド実行はしない。 else Mode='mvCommand' fi } # =================================================================================== # メイン処理を開始 Demo,Action,Command 共通の前処理 # =================================================================================== # グローバル変数_配列を宣言 declare -a -g stdinData IN_DIR_FULL declare -a -g IN_NAME OUT_NAME declare -a -g IN_EXT_DOT OUT_EXT_DOT IN_EXT # IFS_BAK="${IFS}" : '【stdinScan】' && { # stdinの文字列を、配列に格納する while IFS='' read -r FF ; do #-------------------------------------------------↓ # 【ザル】ファイル、ディレクトリのみ通して、パスを正規化 # シンボリックリンクは除外 if test -h "${FF}" ; then continue elif test -f "${FF}" || test -d "${FF}" ; then : && { # 絶対パス取得_変数展開版 case "${FF}" in ( /* ) true ;; ( * ) XX="./${FF#./}" # 頭に「./」があれば削除して、またつける FF="`cd "${XX%/*}" ; pwd`/${FF##*/}" ;; esac } # 絶対パス取得readlink版_多少遅い # FF=`readlink --canonicalize-existing "${FF}"` else echo "${FF}:処理対象のファイル、またはディレクトリがありません。" 1>&2 exit 1 fi # ファイル、ディレクトリ情報取得 if test -f "${FF}" ; then # ==== ファイル ========================= stdinData+=("${FF}") # 正規化した入力行 全て IN_DIR_FULL+=("${FF%/*}") # ディレクトリパス XX="${FF##*/}" # temp ファイル名+拡張子 IN_NAME+=("${XX%%.*}") # すべての「.〜」を拡張子と見なす OUT_NAME+=("${XX%%.*}") # リネーム予定ファイル名_初期値 # sedで拡張子を得るとき #YY=`echo "${XX}" | sed -e 's/^[^.]*//'` # IN_EXT_DOT+=("${YY}") # 「.」つき(に、sedの都合でせざるを得ない) # IN_EXT+=("${YY#.}") # 「.」を削る(変数用のみ、処理には使わない) # OUT_EXT_DOT+=("${YY}") # リネーム予定拡張子_初期値 : '変数展開で拡張子を得るとき' && { if test "${XX}" = "${XX#*.}" ; then # 「.」無し拡張子を得る削除展開 # 拡張子が無いとき、削除展開しても何も削れない IN_EXT_DOT+=('') # IN_EXT+=('') OUT_EXT_DOT+=('') else # ドットファイル...OK,通常拡張子...OK,二重拡張子...OK IN_EXT_DOT+=(".${XX#*.}") # 「.」追加_処理用 # IN_EXT+=("${XX#*.}") # 変数用のみ OUT_EXT_DOT+=(".${XX#*.}") # リネーム予定拡張子_初期値 fi } elif test -d "${FF}" ; then # ==== ディレクトリ ================== stdinData+=("${FF}") # 正規化した入力行 全て IN_DIR_FULL+=("${FF%/*}") # ディレクトリの親ディレクトリ IN_NAME+=("${FF##*/}") # ディレクトリは全てファイル名と見なす OUT_NAME+=("${FF##*/}") # リネーム予定ディレクトリ名_初期値 IN_EXT_DOT+=('') # ディレクトリは拡張子が無いと見なす # IN_EXT+=('') # 変数用のみ、処理には使わない OUT_EXT_DOT+=('') # 拡張子は空に fi done #0< <( cat - ) # -----------------------------------------------------------------------↑ } : '【データベース情報作成(Core自動作成分)】' && { case "${databaseFlag}" in ( true ) for MM in "${!stdinData[@]}" ; do # ---- コピー作成分 ----------------------------------- # 『path』ファイルの絶対パス 「stdinData[]」のコピー DATA_BASE[path_${MM}]="${stdinData[${MM}]}" DATA_BASE[path]="${DATA_BASE[path_0]}" # 『dirfull』ファイルのディレクトリ_フル「IN_DIR_FULL[]」のコピー DATA_BASE[dirfull_${MM}]="${IN_DIR_FULL[${MM}]}" DATA_BASE[dirfull]="${DATA_BASE[dirfull_0]}" # 『name』ファイルの名前 「[IN_NAME]」のコピー DATA_BASE[name_${MM}]="${IN_NAME[${MM}]}" DATA_BASE[name]="${DATA_BASE[name_0]}" # 『extdot』ファイルの拡張子「.」つき 「IN_EXT_DOT[]」のコピー DATA_BASE[extdot_${MM}]="${IN_EXT_DOT[${MM}]}" DATA_BASE[extdot]="${DATA_BASE[extdot_0]}" # ---- 新規作成分 ファイルパス ---------------------- # 『ext』ファイルの拡張子「頭の.」なし 「IN_EXT[]」の「先頭.」を削る DATA_BASE[ext_${MM}]="${IN_EXT_DOT[${MM}]#.}" DATA_BASE[ext]="${IN_EXT_DOT[0]#.}" # 『dir』ファイルのディレクトリ_親一つのみ「IN_DIR_FULL[]」から作成 DATA_BASE[dir_${MM}]="${IN_DIR_FULL[${MM}]##*/}" DATA_BASE[dir]="${IN_DIR_FULL[0]##*/}" done ;; ( false | * ) true ;; esac } : '【${CMD_1D[]}の「$」を一次加工】' && { # CMD_VAR_MODE=escape 「$」->「\\$」 # CMD_VAR_MODE=database 「$」->「$VAR -> ${VAR} ->${DATA_BASE[VAR]}」 # CMD_VAR_MODE=shell 「$」->「$」そのまま for NN in ${!CMD_1D[@]} ; do case "${CMD_VAR_MODE[${NN}]}" in ( escape ) # CMD_1D[${NN}]=`echo "${CMD_1D[${NN}]}" | # sed -e 's/\$\([a-zA-Z0-9_][a-zA-Z0-9_]*\)/${\1}/g;s/\${[a-zA-Z0-9_][a-zA-Z0-9_]*}/\\\\&/g'` CMD_1D[${NN}]=`echo "${CMD_1D[${NN}]}" | sed -e 's/\\$/\\\\$/g'` ;; ( database ) CMD_1D[${NN}]=`echo "${CMD_1D[${NN}]}" | sed -e 's/\$\([a-zA-Z0-9_][a-zA-Z0-9_]*\)/${\1}/g;s/\${\([a-zA-Z0-9_][a-zA-Z0-9_]*\)}/${DATA_BASE[\1]}/g'` ;; ( shell ) true ;; ( * ) echo 'ERR:CMD_VAR_MODE:不正な値' 1 >&2 exit 2 ;; esac done #echo "${databaseSW}" 1>&2 # debug #echo "${CMD_1D[*]}" 1>&2 # debug } #echo ${SECONDS}:'連想配列CMD_2D作成開始' 1>&2 # 【debug】seconds : '【${CMD_1D[]}から連想配列${CMD_2D[]}を作成_sed_遅い】' || { # ▼ stdin取得後に実行する # 一次配列「CMD_1D」中の「${変数名}」を、 # ${DATA_BASE[変数名_数字]}に書き換え、二次配列CMD_2D作成 for NN in "${!CMD_1D[@]}" ; do # コマンドの横列、連想配列nameCmd2d左の数字 case "${CMD_VAR_MODE[${NN}]}" in ( escape | shell ) for MM in "${!stdinData[@]}" ; do # ファイルごとのコマンドを作成、CMD_2D右の数字 # 変換しないでコピーのみ CMD_2D[${NN}_${MM}]="${CMD_1D[${NN}]}" done ;; ( database ) for MM in "${!stdinData[@]}" ; do # ファイルごとに異なるコマンドを作成、CMD_2D右の数字 # ${DATA_BASE[VAR]} -> ${DATA_BASE[VAR_${MM}]} CMD_2D[${NN}_${MM}]=`printf "%s\n" "${CMD_1D[${NN}]}" | sed -e 's/\(\${DATA_BASE\[[^]]*\)\]}/\1_'${MM}']}/g'` done ;; esac done } : '【${CMD_1D[]}から連想配列${CMD_2D[]}を作成_付け焼き刃awk】' && { # ▼ stdin取得後に実行する # 一次配列「CMD_1D」中の「${変数名}」を、 # ${DATA_BASE[変数名_数字]}に書き換え、二次配列CMD_2D作成 for NN in "${!CMD_1D[@]}" ; do # コマンドの横列、連想配列nameCmd2d左の数字 case "${CMD_VAR_MODE[${NN}]}" in ( escape | shell ) # 変換しないでコピーのみ for MM in "${!stdinData[@]}" ; do CMD_2D[${NN}_${MM}]="${CMD_1D[${NN}]}" done ;; ( database ) # ファイルごとに異なるコマンドを作成、CMD_2D右の数字 # ${DATA_BASE[VAR]} -> ${DATA_BASE[VAR_${MM}]} XX="-1" while read -r LL ; do XX=$(( ${XX} + 1 )) CMD_2D[${NN}_${XX}]="${LL}" done 0< <( for MM in "${!stdinData[@]}" ; do printf "%s\n" "${CMD_1D[${NN}]}" done | awk '{ print gensub( "\\${DATA_BASE\\[([^]]*)\\]}","\\${DATA_BASE[\\1_" NR-1 "]}","g",$0 ) }' ) ;; esac done } : '【リネームコマンド全表示確認】' && { case "${Mode}" in ( renameCommandFull ) for NN in "${!CMD_1D[@]}" ; do echo '=== '"[${NN}]: ${CMD_1D[${NN}]} ==========>[${cmdTargetSW},${cmdActionSW}]" for MM in "${!stdinData[@]}" ; do echo " [${NN}_${MM}]: ${CMD_2D[${NN}_${MM}]}" done done 1>&2 #echo ${SECONDS}:'連想配列CMD_2D作成終了' 1>&2 # 【debug】seconds exit 0 ;; ( * ) true ;; esac } : '【名前・拡張子_加工コマンド_実行ループ】' && { for NN in "${!CMD_TARGET[@]}" ; do # -------------------------------------------------↓ #echo "${NN}":${CMD_ACTION[${NN}]}:"${CMD_1D[${NN}]}" 1>&2 # debug case "${CMD_TARGET[${NN}]}" in # ============================================================================== ( name ) # ============================================================================== case "${CMD_ACTION[${NN}]}" in # ----------------------------------------------------------------- ( once ) # ----------------------------------------------------------------- for MM in ${!stdinData[@]} ; do #echo N:${NN} M:${MM} "${CMD_2D[${NN}_${MM}]}" #debug # 1行ごとに異なるコマンド「CMD_2D[]」を実行 set -f eval 'OUT_NAME[${MM}]=`echo "${OUT_NAME[${MM}]}" | '"${CMD_2D[${NN}_${MM}]}"'`' set +f done ;; # ----------------------------------------------------------------- ( loop ) # ----------------------------------------------------------------- # すべての行を同一コマンド「CMD_1D」で処理 set -f eval 'while read -r LL ; do arrTemp+=("${LL}") done 0< <( for MM in ${!stdinData[@]} ; do echo "${OUT_NAME[${MM}]}" done | '"${CMD_1D[${NN}]}"' )' set +f OUT_NAME=("${arrTemp[@]}") unset arrTemp ;; ( * ) true ;; esac ;; # ============================================================================== ( ext ) # ============================================================================== case "${CMD_ACTION[${NN}]}" in # --------------------------------------------------------------------------- ( once ) # --------------------------------------------------------------------------- for MM in ${!stdinData[@]} ; do set -f eval 'OUT_EXT_DOT[${MM}]=`echo "${OUT_EXT_DOT[${MM}]}" | '"${CMD_2D[${NN}_${MM}]}"'`' set +f done ;; # --------------------------------------------------------------------------- ( loop ) # --------------------------------------------------------------------------- set -f eval 'while read -r LL ; do arrTemp+=("${LL}") done 0< <( for MM in ${!stdinData[@]} ; do echo "${OUT_EXT_DOT[${MM}]}" done | '"${CMD_1D[${NN}]}"' )' set +f OUT_EXT_DOT=("${arrTemp[@]}") unset arrTemp ;; ( * ) true ;; esac ;; esac done # --------------------------------------------------------------------------------↑ } #echo ${SECONDS}:'結果を出力' 1>&2 # 【debug】seconds # ==== 結果を出力 ====================================================================== case "${Mode}" in ( Action ) # ---- リネーム実行 ---------------------------------------- for NN in ${!stdinData[@]} ; do cd -- "${IN_DIR_FULL[${NN}]}" for MM in 0.2 1 ; do # MMはリネーム試行回数とsleep時間 if test "${IN_NAME[NN]}${IN_EXT_DOT[NN]}" = "${OUT_NAME[NN]}${OUT_EXT_DOT[NN]}" ; then echo "${IN_NAME[NN]}${IN_EXT_DOT[NN]}"':ファイル名に変更はありません' 1>&2 break 1 elif mv --verbose --no-clobber \ -- "${IN_NAME[NN]}${IN_EXT_DOT[NN]}" "${OUT_NAME[NN]}${OUT_EXT_DOT[NN]}" then break 1 else sleep ${MM} continue 1 fi exit 2 done done ;; ( pipeFull ) # ---- リネーム後ファイル名のみ、フルパスで表示 ------------ for NN in ${!stdinData[@]} ; do echo "${IN_DIR_FULL[NN]}/${OUT_NAME[NN]}${OUT_EXT_DOT[NN]}" done ;; ( pipeNameExt ) for NN in ${!stdinData[@]} ; do echo "${OUT_NAME[NN]}${OUT_EXT_DOT[NN]}" done ;; ( pipeName ) for NN in ${!stdinData[@]} ; do echo "${OUT_NAME[NN]}" done ;; ( pipeExt ) for NN in ${!stdinData[@]} ; do echo "${OUT_EXT_DOT[NN]}" done ;; ( Csv ) # リネーム前後のフルパスファイル名のみをタブ区切りで表示 for NN in ${!stdinData[@]} ; do echo "${IN_DIR_FULL[NN]}/${IN_NAME[NN]}${IN_EXT_DOT[NN]}"' '\ "${IN_DIR_FULL[NN]}/${OUT_NAME[NN]}${OUT_EXT_DOT[NN]}" done ;; ( mvCommand | * ) # ---- mvコマンドを表示 ------------------------ for NN in ${!stdinData[@]} ; do echo 'cd -- '\'"${IN_DIR_FULL[${NN}]}"\'' ; '\ 'mv -n -v -- '\'"${IN_NAME[NN]}${IN_EXT_DOT[NN]}"\'' '\'"${OUT_NAME[NN]}${OUT_EXT_DOT[NN]}"\'' ; ' done ;; esac exit 0