Skip to content

Instantly share code, notes, and snippets.

@photonxp
Last active October 6, 2018 03:57
Show Gist options
  • Save photonxp/2d718c7732a2acb1508e7b67817efa4d to your computer and use it in GitHub Desktop.
Save photonxp/2d718c7732a2acb1508e7b67817efa4d to your computer and use it in GitHub Desktop.
Make the job of renaming files in the shell a little bit easier
#!/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"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment