sh 使shell中的文件重命名更容易

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了sh 使shell中的文件重命名更容易相关的知识,希望对你有一定的参考价值。

#!/bin/bash

# Features:
#     Renaming file or files by batch with the shell script.
#     Rename by multiple pairs of file names.
#     Use the `mv` command along with `grep` etc. underlyingly.
#     A rather simplified alternative to the `rename` shipped by some linux systems.

# Usage:
#     1. Rename a file by one pair of file names:
#         ./rename_files.bash f1_name f2_name
#         ./rename_files.bash ./dir_old ./dir_new
#         f1_name could be in the format of:
#             ./old_fname.txt or old_fname.txt
#             ./old_dirname or old_dirname
#             ~/old_dirname
#             /path/to/old_dir
#         f2_name should be the file/dir name that would be changed to
#             and shouldn't include the upper level parent path

#     2. Rename files by multiple pairs of file names:
#         ./rename_files.bash "f1_old1 f1_old2 .." "f2_new1 f2_new2 .."
#         The number of f1 names should be the same as f2 names:
#         e.g. ./rename_files.bash "./fname1.txt ~/dirname1" "fname2.txt dirname2"
#              ./rename_files.bash "dirname1 /path/to/dir1" "dirname2 dir2"
#              ./rename_files.bash "./{dirA1,dirB1}" "dirA2 dirB2"
#              ./rename_files.bash "./{dirA1,dirB1} c1" "dirA2 dirB2 c2"

# ####test_rename_files.bash:
# #!/bin/bash
#
# # Test the usage of rename_files.bash
# # Operation on some files would fail on purpose
# #     to show failure cases
#
# echo "Start test ============================="
# #
# if [[ -e ./test9 && "-o" != "$1" ]]
#     then
#     echo "Dir test9 existed. Quit."
#     exit 1
# fi
# #
# rm -r ./test9
# mkdir -p ./test9/dir1
# touch ./test9/t.old
#
# ./rename_files.bash "./test9/a1 ./test9/{t.old,dir1}" "a2 t.new dir2"
# 


echo "Start script ============================="
str_raw_paths_of_f1=$1
#str_raw_paths_of_f1="t1 ~/s1 /path_to/m1/ ~/{a1,b1}"
str_names_of_f2=$2
#str_names_of_f2="t2 s2 m2 a2 b2"

# Raw path format: ~/dir{1,2}/
# expanded path format: /home/user/dir1/ /home/user/dir2/
# fine path format: /home/user/dir1 /home/user/dir2

expand_path(){
    # raw path format: ~/s1 /path/to/t1/ m1 ~/{s1,s2}
    str_expanded_paths_of_f1=$(eval echo "$str_raw_paths_of_f1")
}

check_num_of_paths_and_names(){    
    arr_expanded_paths_of_f1=($str_expanded_paths_of_f1)
    arr_names_of_f2=($str_names_of_f2)
    
    if [ ${#arr_expanded_paths_of_f1[@]} -ne ${#arr_names_of_f2[@]} ] 
        then
        echo "Notice:: The number of old files and the number of new names" 
        echo "NOtice::      are not matched."
        echo "Notice:: Exit."
        exit 1
    fi
}

make_fine_path(){
    expanded_path=$1   
    # remove trailing slash "/" in expanded_path
    fine_path=${expanded_path%/}
}

make_path_vars_of_f1_f2_by_path_withslash(){
    f1_path="$1"
    f2_name="$2"    
    f1_parent_path=${f1_path%/*}
    f2_path=$f1_parent_path/$f2_name
}

make_path_vars_of_f1_f2_by_path_without_slash(){
    # path is like a.txt    
    f1_path="$1"
    f2_path=$f2_name
    f1_parent_path="."
}

make_path_vars_of_f1_f2(){
    expanded_f1_path=$1
    f2_name=$2
    
    make_fine_path "$expanded_f1_path"
    
    # arr cmd is usually easier than str cmd
    #     and safer than `eval`
    # grep doesn't work with printf and pipe in arr command mode
    # So use the command line in the shell
    printf "$fine_path" | grep -q '/'
    if [ 0 -eq $? ]
        then
        make_path_vars_of_f1_f2_by_path_withslash "$fine_path" "$f2_name"
    else
        make_path_vars_of_f1_f2_by_path_without_slash "$fine_path" "$f2_name"
    fi
}

mv_files_by_arr_path_vars_of_f1_f2(){
    length=${#arr_names_of_f2[@]}
    for ((i=0; $i<$length; i++))
        do
        echo $i
        expanded_f1_path=${arr_expanded_paths_of_f1[$i]}
        f2_name=${arr_names_of_f2[$i]}
        make_path_vars_of_f1_f2 "$expanded_f1_path" "$f2_name"
        
        arr_paths_of_f1[$i]="$f1_path"
        arr_paths_of_f2[$i]="$f2_path"
             
        mv_cmd="mv $f1_path $f2_path"
        printf "$mv_cmd \n"
        $mv_cmd
    done
    # echo "arr_paths_of_f1:" ${arr_paths_of_f1[@]}
}

main(){
    expand_path
    check_num_of_paths_and_names
    mv_files_by_arr_path_vars_of_f1_f2
}

#################################
main
#!/bin/bash

# Test the usage of rename_files.bash
# Operation on some files would fail on purpose
#     to show failure cases

echo "Start test ============================="
#
if [[ -e ./test9 && "-o" != "$1" ]] 
    then
    echo "Dir test9 existed. Quit."
    exit 1 
fi
#
rm -r ./test9
mkdir -p ./test9/dir1
touch ./test9/t.old 

./rename_files.bash "./test9/a1 ./test9/{t.old,dir1}" "a2 t.new dir2"

以上是关于sh 使shell中的文件重命名更容易的主要内容,如果未能解决你的问题,请参考以下文章

shell备份,重命名,删除目录下面的文件

递归重命名文件 Mac OSX

如何批量重命名带有序列号的照片文件夹中的文件

sh 在Shell中批量重命名

SHELL:多文件的重命名和移动

sh 重命名目录树中的文件扩展名