sh 重命名shell中的链接文件对。通过多对链接文件名重命名。

Posted

tags:

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

#!/bin/bash

# The bubbles in the asset markets 
#     are equivalent to various taxes,
#     payed by each of us in the long term,
#     whether a winner or loser in the game.

# Features:
# Change a pair of link files 
#     from
#         link1.old -> target1.old
#     to
#         link1.new -> target1.new
# Rename by multiple pairs of link file names
# A lightweight alternative to other heavy tools.

# Dependency:
# The `realpath` package is required
# Use the commands of `mv`,`ln`,`rm` etc. underlyingly.

# Usage:
# Link and target files should have the same new name, 
#     but not necessarily the same old name.
# 1. Rename link/target by one pair of file names:
#        ./rename_linkets.bash link_old_path new_name
#    The link_old_path could be in the format of:
#        ./old_link.yy or old_link.yy
#        ./old_link or old_link
#        ~/old_link
#        /path/to/old_link
#    The new_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_linkets.bash "old_link1 old_link2 .." "new_name1 new_name2 .."
#    The number of old_link files should be the same as new names:
#        ./rename_linkets.bash "./{link1,link2}" "new_name1 new_name2"
#        ./rename_linkets.bash "./{link1,link2} c1" "new_name1 new_name2 c2"

# Linket: 
# A pair of files for linking, that work in the form of:
#     Link file -> Target file

# #!/bin/bash
# 
# # Test the usage of rename_linkets.bash
# # Operation on some files would fail on purpose 
# #     to show failure cases 
# 
# # use ./test_rename_linkets.bash -o 
# #     to override the check on the test dir/files
# 
# echo_start(){
#     echo "Start test $1 ============================="
# }
# 
# init(){
#     echo_start "$1"
#     rm -r ./test9
#     mkdir -p ./test9/dir1 ./test9/dir2
# }
# 
# run_tests(){     
#     if [[ -e ./test9 && "-o" != "$option" ]] 
#         then
#         echo "Dir test9 existed. Quit."
#         exit 1 
#     fi
# 
#     for test in "$@"
#         do
#         init "$test"
#         $test
#     done
# }
# 
# test1(){
#     touch ./test9/b.o
#     touch ./test9/dir2/r.o
#     
#     ln -s ../dir2/t.o ./test9/dir1/t.o
#     ln -s "../dir2/r.o" ./test9/dir1/r.o
# 
#     ./rename_linkets.bash "./test9/a.o test9/b.o ./test9/dir1/{t.o,r.o}" "a.n b.n t.n r.n"
# }
# 
# test2(){
#     if [ "-o" != "$option" ] 
#         then
#         for f in `echo "u.o u.n"`
#             do
#             echo "File $f existed. Quit."
#             exit 1 
#         done
#     fi
# 
#     rm u.o u.n ./test9/u.o
#     touch ./test9/u.o
#     ln -s ./test9/u.o u.o 
#     ./rename_linkets.bash u.o u.n
# }
# 
# test3(){
#     # test dangerous path 
#     touch ./test9/dir2/dg.o
#     ln -s ../dir2/dg.o ./test9/dir1/dg.o
#     ./rename_linkets.bash ./test9/dir1/dg.o dg.n
# }
# 
# option="$1"
# 
# #run_tests test1
# #run_tests test2
# #run_tests test3
# run_tests test1 test2
# 

echo "Start script ----------------------"

# f1: old link file or old target file 
#     of the linket (link pair)
# f2: new link file or new target file
#     of the linket (link pair)
# Linket: a pair of files for linking, that work in the form of:
#     Link file -> Target file

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

check_dependency(){
    rslt=$(realpath --version)
    bin_name="${rslt:0:8}"
    if [ "realpath" != "$bin_name" ]
        then
        echo "ERR:: Require the package of realpath, but realpath is not found."
        echo "      To install realpath, run the command of:"
        echo "      sudo apt-get update && sudo apt-get install realpath"
        echo "      Exit."
        exit 1
    fi
}

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

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

check_arg_nums(){
    length_arglist_raw=$#
    
    if [ 2 -gt $length_arglist_raw ]
        then
        echo "ERR:: Lacking operand for $0"
        exit 1
    fi
    
    check_nums_of_path_and_name
}

check_if_link_file_exist(){
    expanded_f1_path="$1"
    
    # tricky test conditions here.
    if [ -h "$expanded_f1_path" ] 
        then
        # -a not work here, use -e
        if [ ! -e "$expanded_f1_path" ] 
            then
            target_path=$(readlink -m "$expanded_f1_path")
            echo "NOTICE:: Broken link: $expanded_f1_path -> $target_path"
            return 1
        fi
        return 0
    fi
    
    if [ ! -f "$expanded_f1_path" ] 
        then
        echo "NOTICE:: Couldn' find linket link file for path: $expanded_f1_path"
        return 1
    fi
    
    if [ -f "$expanded_f1_path" ] 
        then
        echo "NOTICE:: Not a linket link file, but a regular file: $expanded_f1_path"
        return 1
    fi
}

check_if_is_dangerous_path(){
    fpath="$1"
    ftype="$2"
    
    # 1 means "no danger", 0 means "has danger"
    path_has_danger=1
    
    dangerous_path_list=("/")
    #dangerous_path_list=("~/data_mnt/_____data/linux/command_tool/mv/rename_linkets/test9/dir1/dg.o")
    for dangerous_path in "${dangerous_path_list[@]}"
    do
        if [ "$dangerous_path" == "$fpath" ]
            then
            path_has_danger=0
            info="$2 old path has dangerous path "$dangerous_path" in : $fpath"
            echo "ERR:: $info. Exit."
            exit 1
        fi
    done
}

make_f2path_by_f1path_f2name(){
    # make f2path for either link or target
    # by their f1path and new name
    f1_path=$1
    f2_name=$2

    f1_parent_path=${f1_path%/*}
    f2_path=$f1_parent_path/$f2_name
}

make_paths_of_linket_link(){
    make_f2path_by_f1path_f2name "$f1_path_of_link" "$f2_name"
    f2_path_of_link=$f2_path

    ftype="Linket-link"
    check_if_is_dangerous_path "$f1_path_of_link" "$ftype"
}

make_paths_of_linket_target(){
    f1_path_of_target=$(realpath "$f1_path_of_link")   
    make_f2path_by_f1path_f2name "$f1_path_of_target" "$f2_name"
    f2_path_of_target=$f2_path
    
    ftype="Linket-target"
    check_if_is_dangerous_path "$f2_path_of_target" "$ftype"
}

make_paths_of_linket(){   
    # Linket: a pair of files for linking, that work in the form of:
    #     Link file -> Target file
    f1_path_of_link=$(realpath -s "$1")
    f2_name=$2
    
    make_paths_of_linket_link
    make_paths_of_linket_target
}

make_paths_of_linket_in_oneloop(){
    make_paths_of_linket "$expanded_f1_path" "$f2_name"    

    # keey the arr for future debug info
    arr_f1_paths_of_link[$i]=$f1_path_of_link
    arr_f2_paths_of_link[$i]=$f2_path_of_link
    arr_f1_paths_of_target[$i]=$f1_path_of_target
    arr_f2_paths_of_target[$i]=$f2_path_of_target
}

mv_target_file(){
    cmd="mv $f1_path_of_target $f2_path_of_target"
}

ln_new_target_file(){
    cmd="ln -s $f2_path_of_target $f2_path_of_link"
}

rm_old_link_file(){
    cmd="rm $f1_path_of_link"
}

do_linket_by_steps(){
    do_file_steps=("mv_target_file" "ln_new_target_file" "rm_old_link_file")

    for make_cmd_by_step in "${do_file_steps[@]}"
        do
        $make_cmd_by_step
        printf "$cmd \n"
            if ! $cmd
                then
                echo "NOTICE:: Operation failed."
                return 1
            fi
    done
}

rename_linkets(){
    length=${#arr_names_of_f2[@]}
    for (( i=0; $i<$length; i++ ))
        do
        echo $i
        
        f2_name=${arr_names_of_f2[$i]}
        expanded_f1_path="${arr_expanded_paths_of_f1[$i]}"    
        check_if_link_file_exist "$expanded_f1_path"
        if [ 0 -ne $? ]
            then
            continue
        fi

        make_paths_of_linket_in_oneloop
        do_linket_by_steps
    done

    #echo "arr_f1_paths_of_target:" ${arr_f1_paths_of_target[@]}
}

main(){
    check_dependency
    str_raw_paths_of_f1="$1"
    str_names_of_f2="$2"
    
    expand_path
    check_arg_nums "$@"
    rename_linkets
}

####################################
main "$@"
#!/bin/bash

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

# use ./test_rename_linkets.bash -o 
#     to override the check on the test dir/files

echo_start(){
    echo "Start test $1 ============================="
}

init(){
    echo_start "$1"
    rm -r ./test9
    mkdir -p ./test9/dir1 ./test9/dir2
}

run_tests(){     
    if [[ -e ./test9 && "-o" != "$option" ]] 
        then
        echo "Dir test9 existed. Quit."
        exit 1 
    fi

    for test in "$@"
        do
        init "$test"
        $test
    done
}

test1(){
    touch ./test9/b.o
    touch ./test9/dir2/r.o
    
    ln -s ../dir2/t.o ./test9/dir1/t.o
    ln -s "../dir2/r.o" ./test9/dir1/r.o

    ./rename_linkets.bash "./test9/a.o test9/b.o ./test9/dir1/{t.o,r.o}" "a.n b.n t.n r.n"
}

test2(){
    if [ "-o" != "$option" ] 
        then
        for f in `echo "u.o u.n"`
            do
            echo "File $f existed. Quit."
            exit 1 
        done
    fi

    rm u.o u.n ./test9/u.o
    touch ./test9/u.o
    ln -s ./test9/u.o u.o 
    ./rename_linkets.bash u.o u.n
}

test3(){
    # test dangerous path 
    touch ./test9/dir2/dg.o
    ln -s ../dir2/dg.o ./test9/dir1/dg.o
    ./rename_linkets.bash ./test9/dir1/dg.o dg.n
}

option="$1"

#run_tests test1
#run_tests test2
#run_tests test3
run_tests test1 test2

以上是关于sh 重命名shell中的链接文件对。通过多对链接文件名重命名。的主要内容,如果未能解决你的问题,请参考以下文章

重命名链接表 MDB 文件对中的字段?

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

用shell命令对文件重命名

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

学妹拉着我的胳膊让我给她写个显示当前时间的shell脚本,顺手教教学妹硬链接和软链接

sh 在Shell中批量重命名